欢迎您光临深圳塔灯网络科技有限公司!
电话图标 余先生:13699882642

网站百科

为您解码网站建设的点点滴滴

Flutter系列(三):基础控件解析

发表日期:2019-01 文章编辑:小灯 浏览次数:2852

一:Widget

在flutter中,一切的显示都是在Widget中,Widget 是一切显示的基础。
作为响应式的渲染,属于 MVVM 的实现机制。我们可以通过修改数据,再用setState 设置数据,Flutter 会自动通过绑定的数据更新 Widget 。所以我们需要做的就是实现 Widget 界面,并且将其与对应的数据绑定起来。
那么这里是不是又只能用setState进行响应式的开发呢?并不是的。
Widget作为抽象类,下面是分为有状态(StatefulWidget)和无状态(StatelessWidget)两种的。而这里的有状态Widget就是进行响应式开发来使用的,而无状态的StatelessWidget同样可以使用,来进行构造不需要变化的控件。

我们来看看Widget 1.PNG

这里是我根据继承关系绘制的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所希望的大小。

二:StatelessWidget

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), ), ); } } 
2.PNG

如图所示。

三:StatefulWidget

需要创建管理的是主要是 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的生命周期:

  • initState :初始化
  • didChangeDependencies:在 initState 之后调用,此时可以获取其他 State 。
  • dispose :销毁,只会调用一次。

注意一下 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,以便于测试我们需要的效果,'), ), ], ) ); } } 

测试效果如图:


3.PNG
本页内容由塔灯网络科技有限公司通过网络收集编辑所得,所有资料仅供用户学习参考,本站不拥有所有权,如您认为本网页中由涉嫌抄袭的内容,请及时与我们联系,并提供相关证据,工作人员会在5工作日内联系您,一经查实,本站立刻删除侵权内容。本文链接:https://dengtar.com/17533.html
相关APP开发
 八年  行业经验

多一份参考,总有益处

联系深圳网站公司塔灯网络,免费获得网站建设方案及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

业务热线:余经理:13699882642

Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.