Android控件 vs Flutter控件

一. 開始

在Android中View是所有控件的基礎, 在Flutter中與View對等的是Widget. 但Widget又不同于Android中的views. 在Flutter中你可以聲明構造界面.

Flutter中的控件不能修改, 一直到它們需要改變. 當狀態發生變更, Flutter的底層會重新創建一顆新的控件樹實例. 而在Android中控件繪制一次就不再繪制, 直到invalidate被調用.

由于不可變性, Flutter的控件很輕量. 因為它們不是視圖本身,也不是直接繪制任何東西,而是對UI及其語義的描述. 最終才會被構造成實際的試圖對象.

二. Android控件

常用基礎控件View, TextView, Button, ImageView, 其它控件如ProgressBar, SeekBar等.
這些控件都繼承自View. 基礎控件不夠用時, 可繼承這些控件實現自己想要的特性.

在android中存在5種基本布局

  • 線性布局(LinearLayout)
  • 相對布局(RelativeLayout)
  • 表格布局(TableLayout)
  • 幀布局(FrameLayout)
  • 絕對布局(AbsoluteLayout)

TableLayout和AbsoluteLayout我基本沒有用到. LinearLayout用于布局水平一行或者縱向一行.
FrameLayout用于布局有層次的界面, 可以簡單設置居中. 更復雜控件間的相對關系使用RelativeLayout布局.

FrameLayout性能會好于RelativeLayout, 當FrameLayout無法解決的時候才用RelativeLayout
RelativeLayout通過相對關系也能布局出LinearLayout的界面, 但不如LinearLayout直觀

列表可滑動滑動布局ScrollView/ListView/GridView/RecyclerView/ViewPager.

上述控件繼承自ViewGroup, ViewGroup又繼承于View 相對于繼承View的控件, 前者內部可包含子控件, 而后者不行.前者一般會實現onLayout和onMeasure, 來控件子控件的布局和大小. 這些布局不夠用時, 也可繼承這些控件實現自己想要的特性.

上述所有控件都有的屬性有

  • 寬度(layout_width)
  • 高度(layout_height)
  • 背景(backgroud)
  • 內間距(padding)
  • 外間距(margin)
  • 可見性(visibility)
  • 位于父控件的位置(layout_gravity)
  • 內部子控件的位置(gravity, 繼承自ViewGroup的才有)
  • 點擊事件(onClick)
  • 動畫屬性(alpha/rotation/scale)

三. Flutter控件

flutter中的控件非常多, 每一種布局只具備特定的特性. 功能劃分的非常細. 最大的不同也正是這點, 基本控件不再擁有通用屬性,比如背景, 點擊事件等, 這些都被獨立出來成為單獨的控件.

舉個簡單例子如下

Android例子

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:onClick="xxx"
        android:gravity="center"
        android:text="按鈕"
        android:textSize="18sp"
        android:textColor="0xffffffff"
        android:layout_width="100dp"
        android:layout_height="40dp"
        android:background="0xff808080"/>
</LinearLayout>

Flutter例子

var layout = Column(
  children: <Widget>[
    GestureDetector(
      child: Container(
        width: 100.0,
        height: 40.0,
        color: Color(0xff808080),
        child: Center (
          child: Text(
            '按鈕',
            style: TextStyle(
              color: Color(0xffffffff),
              fontSize: 18.0,
            ),
          ),
        )
      ),
      onTap: () {
        print('clicked');
      },
    ),
  ],
);

可以看出在Flutter中, 屬性都被提取成一個控件了, GestureDetector負責處理點擊事件, Container負責大小和背景, Center負責居中.Text僅僅只有文字相關的屬性, 這樣Android一個簡單的控件在Flutter中需要嵌套很多層才能實現. 但好處就是劃分的很細, 可以任意組合.

基本的顯示控件有Text, Image, Icon, RaisedButton等.屬性功能控件有Container, Padding, Center, Align, FittedBox等.這些都是Single-child控件. 就是child屬性指向為Widget.

布局控件有Row, Column, Stack, IndexedStack, GridView, ListView等.這些都是Multi-child控件. 就是child屬性指向為<Widget>[].

四. 實現自定義控件

在Android中通常是繼承View或其它基于View的控件. 然后重寫其中的方法, 來獲取想要的行為.

在Flutter中, 你只需要組合各種小組件而不是繼承. 某種程度上類似于實現Android中的一個自定義ViewGroup. 各種組件單元都已經存在, 你只是提供一種不同的行為, 比如, 重新定義布局邏輯.

舉個例子: 你想實現一個在構造時獲取文字的CustomButton. 你可以通過RaisedButton組合文字, 而不是繼承RaisedButton.

class CustomButton extends StatelessWidget {
  final String label;

  CustomButton(this.label);

  @override
  Widget build(BuildContext context) {
    return RaisedButton(onPressed: () {}, child: Text(label));
  }
}

然后使用CustomButton就像跟其它Flutter組件一樣:

@override
Widget build(BuildContext context) {
  return Center(
    child: CustomButton("Hello"),
  );
}

五. Android/Flutter映射表

Android Flutter
TextView Text
ImageView Image
Button RaisedButton
LinearLayout Row/Column
FrameLayout/RelativeLayout Stack
ListView ListView
GridView GridView
ViewPager PageView
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,558評論 25 708
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,554評論 0 17
  • 很多時候,一本書,一幅畫,一段音樂,靜靜的繪畫,靜靜的思考,靜靜中把往事一絲一縷的整理。時光能給我們的,唯有...
    圖媽0302閱讀 310評論 0 0
  • 詩書繼世長, 忠厚傳家遠。
    喜亭_bf8f閱讀 160評論 2 7