发表日期:2019-01 文章编辑:小灯 浏览次数:2852
在flutter中,一切的显示都是在Widget中,Widget 是一切显示的基础。
作为响应式的渲染,属于 MVVM 的实现机制。我们可以通过修改数据,再用setState 设置数据,Flutter 会自动通过绑定的数据更新 Widget 。所以我们需要做的就是实现 Widget 界面,并且将其与对应的数据绑定起来。
那么这里是不是又只能用setState进行响应式的开发呢?并不是的。
Widget作为抽象类,下面是分为有状态(StatefulWidget)和无状态(StatelessWidget)两种的。而这里的有状态Widget就是进行响应式开发来使用的,而无状态的StatelessWidget同样可以使用,来进行构造不需要变化的控件。
这里是我根据继承关系绘制的UML图,暂且把需要的先画了,有些简单画的是我觉得没必要说的 hhh
这里最重要的一个父类就是Widget了,里面有个
final Key key;
是所有子类都需要继承并使用的。这里是表示的一个密钥,其实就是控件的标识。注释里说明:
//控制一个Widgets如何替换树中的另一个Widgets。 //如果两个Widgets的[runtimeType]和[key]属性分别是[operator ==],则新Widgets将替换旧//Widgets //更新底层元素(即通过使用新Widgets调用[Element.update])。 //否则,将从树中删除旧元素,将新窗口Widgets扩展为元素,并将新元素插入树中 //此外,使用[GlobalKey]作为窗口Widgets的[key]允许元素在树周围移动(更改父级)而///不会丢失状态。//当找到一个新的Widgets时(它的键和类型与同一位置的前一个Widgets不匹配), //但是在前一帧的树中的某个地方有一个具有相同全局键的Widgets,那么该Widgets的元素将被移动到 新的位置。 //通常,作为另一个Widgets的唯一子节点的Widgets不需要一个明确的密钥。
StatefulWidget和StatelessWidget前面有过叙述,接下来还会进行叙述。我们看看其他三个。
ProxyWidget:提供子窗口Widgets的窗口Widgets,而不是构建新窗口Widgets。 (其下有很多子类)
RenderObjectWidget:提供RenderObjectElement的配置,包装RenderObject,并提供应用程序的实际呈现。(实际就是渲染Widget)
PreferredSizeWidget:Widgets的接口,如果它不受限制,可以返回此Widgets所希望的大小。
Widget 和 Widget 之间通过 child: 进行嵌套。其中有的 Widget 只能有一个 child,而有的Widget可以有多个child。
我们可以写一个demo来测试一下StatelessWidget。
void main() => runApp(MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: new TestDemo(title: 'test demo',) ); } } class TestDemo extends StatelessWidget{ TestDemo({Key key, this.title}) : super(key: key); final String title;@override Widget build(BuildContext context) { // TODO: implement build return new Scaffold( appBar: new AppBar( title: new Text('flutter Bar'), ), body: new Center( child: new Text(title), ), ); } }
可以看到,StatelessWidget类内部一定有一个build方法返回一个Widget。而且home属性传入的是一个Widget。这里的home是调用TestDemo返回了Scaffold。然后MyApp再返回MaterialApp。
MaterialApp是材料App,一般作为APP顶层的主页入口,可配置主题,多语言,路由等。
Scaffold是脚手架,一般用户页面的承载Widget,包含appbar、snackbar、drawer等material design的设定。
AppBar是安卓的ToolBar一样的控件。
里面还可以返回一些其余控件,比如说AppBar有标题,二级页面返回按键。Scaffold有悬浮按钮等。
class TestDemo extends StatelessWidget{ TestDemo({Key key, this.title}) : super(key: key); final String title;@override Widget build(BuildContext context) { // TODO: implement build return new Scaffold( appBar: new AppBar( title: new Text('flutter Bar'), leading: new Icon(Icons.list), ), body: new Center( child: new Text(title), ), floatingActionButton: FloatingActionButton( tooltip: 'Increment', child: new Icon(Icons.add), ), ); } }
如图所示。
需要创建管理的是主要是 State , 通过 State 的 build 方法去构建控件。在 State 中,你可以动态改变数据,也就是继承 State<>的实现。在 setState 之后,改变的数据会触发 Widget 重新构建刷新。
class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title;@override _MyHomePageState createState() => _MyHomePageState(); }class _MyHomePageState extends State<MyHomePage> { int _counter = 0;void _incrementCounter() { setState(() { _counter++; }); }@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( 'You have pushed the button this many times:', ), Text( '$_counter', style: Theme.of(context).textTheme.display1, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } }
这里是默认创建的flutter项目中的代码,大致逻辑就是点击floatingActionButton响应,调用_incrementCounter函数。函数内是setState。setState 之后,改变的数据会触发 Widget 重新构建刷新,更新counter的Text( '$_counter', )
大致逻辑就是如此,需要编写的地方就是继承了state<>的类了,而state的生命周期:
注意一下 child: Column(),这里面是下面要讲的内容:布局。
布局文档
常用的大概有:
Row:一个以水平数组的形式显示其子部件的Widget
children是一个Widget数组(可以有多个子 Widget),当然这里如果一直显示的话会存在越界的情况。
Colum:一个以竖直数组的形式显示其子部件的Widget。
children是一个Widget数组(可以有多个子 Widget)
Container:一个结合了常见的绘制,定位和大小调整Widget
children是一个Widget(只有一个子 Widget),默认充满,包含color、宽高、decoration 等等配置。
Expanded:创建一个Widget,用于展开Row,Column或Flex的子项展开以填充主轴中的可用空间。
children是一个Widget(只有一个子 Widget)。在 Colum 和 Row 中充满。
Stack:一个相对于它的框的边缘来定位它的子部件的Widget。
children是一个Widget数组(有多个子 Widget)。 子Widget堆叠在一起。
Card :大致效果为Android的CardView
children是一个Widget(只有一个子 Widget)
其余还有一些辅助的布局如:Center(),padding()等等。
我们使用一些来试试:
void main() => runApp(MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', home:new TestDemo() ); } }class TestDemo extends StatelessWidget{ @override Widget build(BuildContext context) { // TODO: implement build return new Scaffold( appBar: AppBar( brightness: Brightness.light, title: Text('TestCard'), ),body: Column( children: <Widget>[ Card( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ AspectRatio( aspectRatio: 18.0 / 11.0, child: Icon(Icons.favorite), ), Padding( padding: EdgeInsets.fromLTRB(16.0, 12.0, 16.0, 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text('Title'), SizedBox(height: 8.0), Text('Secondary Text'), ], ), ), ], ), ), Expanded( child:Text('这是一个特别特别特别特别特别长的Text,以便于测试我们需要的效果,'), ), ], ) ); } }
测试效果如图:
日期:2018-10 浏览次数:7540
日期:2018-12 浏览次数:4621
日期:2018-07 浏览次数:5134
日期:2018-12 浏览次数:4415
日期:2018-09 浏览次数:5774
日期:2018-12 浏览次数:10194
日期:2018-11 浏览次数:5106
日期:2018-07 浏览次数:4854
日期:2018-05 浏览次数:5117
日期:2018-12 浏览次数:4580
日期:2018-10 浏览次数:5390
日期:2018-12 浏览次数:6460
日期:2018-11 浏览次数:4716
日期:2018-08 浏览次数:4867
日期:2018-11 浏览次数:12959
日期:2018-09 浏览次数:5877
日期:2018-12 浏览次数:5094
日期:2018-10 浏览次数:4438
日期:2018-11 浏览次数:4791
日期:2018-12 浏览次数:6320
日期:2018-06 浏览次数:4263
日期:2018-08 浏览次数:5712
日期:2018-10 浏览次数:4699
日期:2018-12 浏览次数:4816
日期:2018-07 浏览次数:4629
日期:2018-12 浏览次数:4801
日期:2018-06 浏览次数:4635
日期:2018-11 浏览次数:4617
日期:2018-12 浏览次数:4547
日期:2018-12 浏览次数:5528
Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.