Android(安卓)Flutter:Dart语言(布局篇)
一、Flutter架构
flutter官方文档:https://api.flutter.dev/flutter/widgets/widgets-library.html
flutter架构:
在flutter的世界里,包括views,view controllers,layouts等在内的概念都建立在Widget之上。widget是flutter功能的抽象描述。通过组合不同的 Widget,来实现我们用户交互界面。
Widget 分为两种:
1、无状态的,StatelessWidget,它只能用来展示信息,不能有动作(用户交互)
使用方法:继承 StatelessWidget,实现 build 方法
class FooWidget extends StatelessWidget { @override Widget build(BuildContext context) { // ... }}
2、有状态的,StatefulWidget,可以通过改变状态使 UI 发生变化,包含用户交互。
使用方法:稍微复杂,需要一个 State,例子如下
class BarWidget extends StatefulWidget { @override State createState() { return _BarWidgetState(); }}class _BarWidgetState extends State { @override Widget build(BuildContext context) { // ... }}
二、文本Text
使用 TextStyle,可以对文本的样式进行修改
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Text( "Put your text here", textAlign: TextAlign.center, maxLines: 1, style: TextStyle( color: Colors.blue, fontSize: 16.0, fontWeight: FontWeight.bold ), ); }}
三、图片Image
Flutter中的图片缩放是fit字段来控制的,缩放属性值在BoxFit枚举中。
有:fill、contain、cover,fitWidth、fitHeight、none、scaleDown
图片的来源:网络、文件、资源和内存
Image.asset(name);Image.file(file);Image.memory(bytes);Image.network(src);
例子:
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Image.network( 'https://gw.alicdn.com/tfs/TB1CgtkJeuSBuNjy1XcXXcYjFXa-906-520.png', fit: BoxFit.contain, width: 150.0, height: 100.0, ); }}
四、按钮FlatButton 和 RaisedButton
两种按钮的区别在于样式不同。child 参数用于设置按钮的内容。它可以接受任意的 Widget,比方说,Text,Image;
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { var flatBtn = FlatButton( onPressed: () => print('FlatButton pressed'), child: Text('BUTTON'), ); var raisedButton = RaisedButton( onPressed: () => print('RaisedButton pressed'), child: Text('BUTTON'), ); return raisedButton; }}
五、文本输入框TextField
为了获取用户输入的文本,我们需要给他设置一个 controller。通过这个 controller,就可以拿到文本框里的内容
class MessageForm extends StatefulWidget { @override State createState() { return _MessageFormState(); }}class _MessageFormState extends State { var editController = TextEditingController(); @override Widget build(BuildContext context) { // Row、Expand 都是用于布局的控件,这里可以先忽略它们 return Row( children: [ // 占满一行里除 RaisedButton 外的所有空间 Expanded( child: TextField( controller: editController, ), ), RaisedButton( child: Text("click"), onPressed: () => print('text inputted: ${editController.text}'), ) ], ); }@override void dispose() { super.dispose(); // 手动调用 controller 的 dispose 方法以释放资源 editController.dispose(); }}
六、显示弹框
RaisedButton( child: Text("click"), onPressed: () { showDialog( // 第一个 context 是参数名,第二个 context 是 State 的成员变量 context: context, builder: (_) { return AlertDialog( // dialog 的内容 content: Text(editController.text), // actions 设置 dialog 的按钮 actions: [ FlatButton( child: Text('OK'), // 用户点击按钮后,关闭弹框 onPressed: () => Navigator.pop(context), ) ], ); } ); })
七、Container、Padding 、Center
Flutter的设计思想就是完全的widget化!连最基本的padding,Center都是widget。Container类似于android中的ViewGroup。
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( padding: EdgeInsets.all(8.0), child: Text('text'), ); }}
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.all(8.0), margin: EdgeInsets.all(4.0), width: 200.0, height: 200.0, decoration: BoxDecoration( // 背景色 color: Colors.grey, // 圆角 borderRadius: BorderRadius.circular(5.0), ), // 把文本放在 Container 的中间 child: Center( child: Text('text'), ), ); }}
八、水平布局Row、竖直布局Column
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Row( // 只有一个子元素的 widget,一般使用 child 参数来设置;Row 可以包含多个子控件, // 对应的则是 children children: [ Text('text1'), Text('text2'), Text('text3'), ], ); }}
Column 的使用和Row是一样的
九、Expand 控件
见上面TextField 的例子。通过使用 Expand,TextField 才能够占满一行里除按钮外的所有空间。当一行/列里有多个 Expand 时,我们还可以通过设置它的 flex 参数,在多个 Expand 之间按比例划分可用空间。
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Row( children: [ Expanded( // 占一行的 2/3 flex: 2, child: RaisedButton(child: Text('btn1'),), ), Expanded( // 占一行的 1/3 flex: 1, child: RaisedButton(child: Text('btn2'),), ), ], ); }}
Expanded 只能包含一个子元素,使用的参数名是 child
十、Stack 布局
有些时候,我们可能会希望一个控件叠在另一个控件的上面。于是,Stack 应运而生:
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Stack( children: [ Text('foobar'), Text('barfoo'), ], ); }}
默认情况下,子控件都按 Stack 的左上角对齐,于是,上面的两个文本完全一上一下堆叠在一起。我们还可以通过设置 alignment 参数来改变这个对齐的位置:
class TestWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Stack( // Aligment 的取值范围为 [-1, 1],Stack 中心为 (0, 0), // 这里设置为 (-0.5, -0.5) 后,可以让文本对齐到 Container 的 1/4 处 alignment: const Alignment(-0.5, -0.5), children: [ Container( width: 200.0, height: 200.0, color: Colors.blue, ), Text('foobar'), ], ); }}
实际使用中Stack中的子Widgets分为两种:
- positioned
- 是包裹在组件Positioned中的组件
- 可以通过Positioned属性灵活定位
- non-positioned
- 没有包裹在Positioned组件中
- 需要通过父Widget Stack 的属性来控制布局
new Container( color: Colors.yellow, height: 150.0, width: 500.0, child: new Stack(children: [ new Container( color: Colors.blueAccent, height: 50.0, width: 100.0, alignment: Alignment.center, child: Text('unPositioned'), ), new Positioned( left: 40.0, top: 80.0, child: new Container( color: Colors.pink, height: 50.0, width: 95.0, alignment: Alignment.center, child: Text('Positioned'), )), ]))
通过组合 Row/Column 和 Stack,已经能够完成绝大部分的布局了,所以 Flutter 里没有相对布局之类的东西。
十一、Visibility
在Flutter中,组件中没有visibility属性。visibility的控制还是比较麻烦的。目前有几种方法
1、删除法:
- 单个组件‘隐藏’自己。在build方法中返回一个空的Container.
- 多个child,在父容器的children字段的list中,删除掉对应的cell
2、Offstage的offstage属性设置为true
@overrideWidget build(BuildContext context) { return new Offstage( offstage: !isVisible, child:child);}
3、透明度
设置widget的透明度,使之不可见。但依然会绘制,浪费计算资源,且占据的位置是存在的
十二、state 生命周期
- initState插入渲染树时调用,只调用一次
- didChangeDependenciesstate依赖的对象发生变化时调用
- didUpdateWidget组件状态改变时候调用,可能会调用多次
- build构建Widget时调用
- deactivate当移除渲染树的时候调用
- dispose组件即将销毁时调用
本篇文章大部分内容摘自:https://juejin.im/post/5bd54b7be51d456c430e35f6, https://juejin.im/post/5b8ce76f51882542c0626887 感谢!
更多相关文章
- 底部导航栏中间凸出效果
- Android控件——Checkbox复选框、RadioButton单选、ToggleButton
- android选择一张本机图片
- Android(安卓)短信模块分析(二) MMS中四大组件核心功能详解
- 3.addView调用之后导致子布局的android:layout_width="match_par
- Android(安卓)ConstraintLayout布局详解
- android UI小结(四)
- Android学习笔记01_走马观花
- Listview中Button抢占焦点的解决方法