一. 开始
在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 |
网友评论