Flutter(六)——多子元素组件:ListView,Scaffold,AppBar,Row,Column

简介: Flutter(六)——多子元素组件:ListView,Scaffold,AppBar,Row,Column

前言


Flutter开发中,多子元素组件包括:Scaffold,AppBar,Row,Column,Stack,IndexedStack,ListView,GridView,Flow,Table,Flex,Wrap,CustomScrollView,CustomMultiChildLayout等,下面博主将一一介绍其使用方式。(本文学完能实现如下效果)


Scaffold


Scaffold是基于Material库的一个与路由相关的,良好的“结构体”,它可以被认为是Flutter为我们提供的一个标准化的布局容器,在开发中,使用的频率非常高,所以必须掌握,我们先来看看其使用代码:

return Scaffold(
      appBar: AppBar(),
      body: Row(),
      bottomNavigationBar: ,
      floatingActionButton: 
      ), 
    );


根据上面的代码,我们可以看到,Scaffold结构体为我们很好继承了AppBar,FloatingActionButton等控件。这里我们先认识一下,待介绍完其他组件,在后续章节深入使用。


AppBar


做过Android开发应该一眼就能看出来,这就是一个标题栏组件,用于控制App的路由,显示标题栏,以及显示右侧的一些操作栏。其绘制区域一般位于屏幕的顶端,我们来看看AppBar的整体分布区域图:

从上图我们可以看到,Leading区域默认是隐藏的,但是如果有左侧滑栏时会显示。并且,当这个界面时上一个界面跳转过来的时候,这里会显示返回键,我们来看看具体使用的代码:

appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text("AppBar"),
          actions: [
            IconButton(
              icon: Icon(Icons.playlist_play),
              tooltip: '菜单1',
              onPressed: (){},
            ),
            IconButton(
              icon: Icon(Icons.playlist_add),
              tooltip: '菜单2',
              onPressed: (){},
            ),
            IconButton(
              icon: Icon(Icons.playlist_add_check),
              tooltip: '菜单3',
              onPressed: (){},
            ),
        ],
      ),


大多数情况下,使用上面的代码基本囊括了所有的AppBar常用使用方式,但是,可能我们有些情况还需要自定义标题栏。比如左侧不是返回按钮, 可能是商标,或者别的图标或者点击功能,这个时候我们可以通过重写leading属性,代码如下:

leading: IconButton(
            icon:new Icon(Icons.face),
            onPressed: (){}
),


这样我们就自定义了leading按钮,上面两段代码合并在一起实现的效果如下:


Row和Column


Row和Column在Flutter里的布局是需要我们终点掌握的内容,他们都属于线性布局。从Android层面来理解,类似的布局是LinearLayout,从前端来看,有点像标签。


需要注意的是,Column是不支持滚动的,如果需要实现滚动功能,则要考虑使用ListView。我们先来看看Row。Row是一个多子元素组件,用于在水平方向上防止并显示子组件,Row的基本属性如下表所示:


属性

取值
childred 传入子组件数组
crossAxisAlignment 子组件在纵轴方向上的对齐方式
mainAxisAlignment 子组件在水平方向上的对齐方式
textDirection 布局顺序,一般情况下从左到右
mainAxisSize max,表示尽可能多地占用水平方向上的位置,min则反之

了解Row组件的属性后,我们来看看它的使用代码:

body: Row(
        textDirection: TextDirection.rtl,//从右到左
        children: [
          Container(
            width: 100,
            height: 100,
            color: Colors.blue,
            alignment: Alignment.center,
            child: Text(
              "A",
              style: new TextStyle(color: Colors.white,fontSize: 25),
            ),
          ),
          Spacer(
            flex: 1,
          ),
          Container(
            width: 100,
            height: 100,
            color: Colors.blue,
            alignment: Alignment.center,
            child: Text(
              "B",
              style: new TextStyle(color: Colors.white,fontSize: 25),
            ),
          ),
          Spacer(
            flex: 1,
          ),
          Container(
            width: 100,
            height: 100,
            color: Colors.blue,
            alignment: Alignment.center,
            child: Text(
              "C",
              style: new TextStyle(color: Colors.white,fontSize: 25),
            ),
          ),
        ],
      ),


上面代码不用多说前面已经基本介绍过,除了Spacer,它的作用是创建一个可调整的空间隔,可用于调整Flex容器(如行或列)中窗口小部件之间的间距, 显示效果如下:

接着我们再来看看Column组件,其实它和Row组件基本相似,区别仅仅在于是在垂直方向上放置控件,唯一需要注意的是Row和Column里Cross Axis和Main Axis是不一样的,Row的Main Axis是横方向上的,Column的Main Axis是纵方向上的,Cross Axis同理。


ListView


ListView是Android开发中非常重要的组件,与Java开发Android中的ListView,RecycleView类似,作用都是可滚动项的线性列表,里面存放着相关组件的集合。在一般情况下,这些组件的结构都具有重复性,即每个item的结构相同。


ListView构建方式如下:


(1)ListView


(2)ListView.builder


(3)ListView.custom


(4)ListView.separated


我们来看看它的使用方式,代码如下:

body: ListView(
        padding: const EdgeInsets.all(10.0),
        itemExtent: 30.0,
        children: [
          Text("One"),
          Text("Two"),
          Text("Three"),
          Text("Four"),
          Text("Five"),
        ],
      ),


这算是最基本的使用方式,显示下过如下:

需要解释两个属性,这里itemExtent表示子项的高度,如果是ListView是水平显示,表示子项的宽度,特别注意,尽量设置这个参数,因为这样不需要动态计算,代码运行效率高,至于其他属性,看看下表:


属性 取值

shrinkWrap

是否根据子组件的高度来设置ListView的高度,默认为false
RepaintBoundart 当addRepaintBoundaries为true时,避免列表项滚动时重绘
AutomaticKeepAlive 当addRepaintKeepdaries为true时,则ListView滑出屏幕的区域不会被回收

接着我们再来看看ListView.builder的使用方式(ListView.builder被用于创建重复的子项布局):

body: ListView.builder(
        padding: const EdgeInsets.all(10.0),
        itemExtent: 30.0,
        itemCount: 5,//可以不传
        itemBuilder:(context,position){
        return ListItem();
        }
      ),


因为ListView是懒加载,所以可以不指定itemCount。列表有可能是无限长的,而itemBuilder传入的类型是IndexedWidgetBuilder,只会返回一个组件。当我们滚动到具体的位置因子时,就会创建列表项。


接着,我们来看看ListView.separated。他的作用是“分割”,即在列表子项中夹杂其他项,代码的基本结构如下所示:

ListView.separated(
  itemCount:itemCount,
  itemBuilder:(context,position){
  return ListItem();
  }
  separatorBuilder:(context,position){
  return SeparatorItem();
  }
)


separatorBuilder和itemBuilder基本类似。我们在实际的项目实践中,有可能需要用到分割线来分割列表的每一项item,这个时候ListView.separated就派上用处了。然而,在separatorBuilder里面,不一定只能传入分割线,也可以传入其他东西,比如图片,我们来看看其效果:

body: ListView.separated(
          itemBuilder: (BuildContext context,int index){
            return ListTile(title: Text("第$index列表"));
          },
          separatorBuilder: (BuildContext context,int index){
            return Align(
              alignment: Alignment.centerLeft,
              child: FlutterLogo(),
            );
          },
          itemCount: 20)


显示效果如下图所示:

最后,我们再来看看ListView.custom。它可以通过SliverChildListDelegate来接收IndexedWidgetBuilder,并且为ListView生成列表项,从而实现自定义功能,这里就不赘述了,后续实践中会详细介绍。


以上便是ListView的各种创建方式。我们现在来做一个有意思的效果,这里需要用到ScrollPhysics。这个属性是ListView中的physics上面设置的,包括NeverScrollablePhysics(不滚动效果),BouncingScrollPhysics(IOS效果),ClampingScrollPhysics(Anroid效果),FixedExtentScrollPhysics(固定范围的滚动效果)等,FixedExtentScrollPhysics使用代码如下:

@override
  Widget build(BuildContext context) {
    FixedExtentScrollController fixedExtentScrollController =
    new FixedExtentScrollController();
    final List imgList = [
      'https://img.tukuppt.com//ad_preview/00/10/93/5c993b5d9d798.jpg!/fw/780',
      'https://img.tukuppt.com//ad_preview/00/05/71/5c98de9ce54c3.jpg!/fw/780',
      'https://img.tukuppt.com//ad_preview/00/07/27/5c9902dec7ca4.jpg!/fw/780',
      'https://img.tukuppt.com//ad_preview/00/10/95/5c993bc348d70.jpg!/fw/780',
      'https://img.tukuppt.com//ad_preview/00/04/92/5c98cbc632893.jpg!/fw/780',
      'https://img.tukuppt.com//ad_preview/00/05/74/5c98df32309c8.jpg!/fw/780',
      'https://img.tukuppt.com//ad_preview/00/17/37/5c99cebeb89f6.jpg!/fw/780',
      'https://img.tukuppt.com//ad_preview/00/15/33/5c99a01628499.jpg!/fw/780',
      'https://img.tukuppt.com//ad_preview/00/13/28/5c9970fdc6932.jpg!/fw/780'
    ];
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        leading: IconButton(
            icon:new Icon(Icons.face),
            onPressed: (){}
            ),
        title: Text("AppBar"),
          actions: [
            IconButton(
              icon: Icon(Icons.playlist_play),
              tooltip: '菜单1',
              onPressed: (){},
            ),
            IconButton(
              icon: Icon(Icons.playlist_add),
              tooltip: '菜单2',
              onPressed: (){},
            ),
            IconButton(
              icon: Icon(Icons.playlist_add_check),
              tooltip: '菜单3',
              onPressed: (){},
            ),
        ],
      ),
      body: ListWheelScrollView(
        controller: fixedExtentScrollController,
        physics: FixedExtentScrollPhysics(),
        itemExtent: 150.0,
        children : imgList.map((img){
          return Card(
            child: Row(
              children: [
                Image.network(img,width: 150.0),
                Text("随便文字",style: new TextStyle(color: Colors.black45,fontSize: 20.0),
                ),
              ],
            ),
          );
        }).toList(),
      ),
    );
  }

这段代码的显示的效果如该帖开头动图效果一样,多子元素组件这篇博文就讲到这里,下篇博文介绍剩余组件。

相关文章
|
7月前
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
371 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
8月前
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
259 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
8月前
|
Dart 前端开发 容器
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
222 18
【07】flutter完成主页-完成底部菜单栏并且做自定义组件-完整短视频仿抖音上下滑动页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
6月前
|
索引
【Flutter 开发必备】AzListView 组件全解析,打造丝滑索引列表!
在 Flutter 开发中,AzListView 是实现字母索引分类列表的理想选择。它支持 A-Z 快速跳转、悬浮分组标题、自定义 UI 和高效性能,适用于通讯录、城市选择等场景。本文将详细解析 AzListView 的核心参数和实战示例,助你轻松实现流畅的索引列表。
216 7
|
10月前
|
开发工具
Flutter&鸿蒙next中封装一个列表组件
Flutter&鸿蒙next中封装一个列表组件
162 0
Flutter中Row中的子控件左右两端对齐
Flutter中Row中的子控件左右两端对齐
381 0
|
8月前
flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
flutter开发中Use ‘const’ with the constructor to improve performance. Try adding the ‘const’ keyword to the constructor invocation.报错如何解决-优雅草卓伊凡
108 1
|
7月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
417 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
8月前
|
前端开发 Java 开发工具
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
457 18
【03】完整flutter的APP打包流程-以apk设置图标-包名-签名-APP名-打包流程为例—-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈 章节内容【03】
|
7月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
166 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex