zoukankan      html  css  js  c++  java
  • Flutter: 图解 ListView 的多种绑定方式

       小菜昨天刚学习了一下底部状态栏 BottomNavigationBar 的基本使用方法,今天学习一下 ListView 的基本用法。
          小菜觉得 Flutter 中 ListView 这个控件很强大,它兼顾了 Android 中的 ScrollView 和 ListView 两个控件的效果,既可以当列表用也可以充当可滑动布局。小菜今天主要测试作为普通列表时的基本用法。

                                  效果图1.jpg

    列表 item -> ListTile

          Flutter 很贴心的提供了一种常见的列表 item 样式,可以包括前后图标以及大小标题的样式;小菜特意了解了一下 ListTile 的基本属性,如下:

    const ListTile({
        Key key,
        this.leading,              // item 前置图标
        this.title,                // item 标题
        this.subtitle,             // item 副标题
        this.trailing,             // item 后置图标
        this.isThreeLine = false,  // item 是否三行显示
        this.dense,                // item 直观感受是整体大小
        this.contentPadding,       // item 内容内边距
        this.enabled = true,
        this.onTap,                // item onTap 点击事件
        this.onLongPress,          // item onLongPress 长按事件
        this.selected = false,     // item 是否选中状态
    })

         Tips: 小菜对 dense 属性理解不是很好,直观的感觉是 dense 为 true 时整体会小一些,文字更为明显,就像整体分辨率变高;如下图:

                               dense 为 false.jpg

    列表 -> ListView

          Flutter 中 ListView 用法与 Android 中类似,首先添加数据,之后绑定列表;Flutter 中绑定列表有四种方式,分别是 默认 List / ListView.builder / ListView.separated / ListView.custom;小菜主要对前三种方式逐一测试;如图:

    无论是用那种绑定数据的方式首先第一步都要添加数据,小菜测试基本样式包括 item 前置图标(leading)、标题文字(title)、后置图标(trailing),并设置了基本的 onTap() 方法;如下:

    List<String> strItems = <String>[
        '图标 -> keyboard', '图标 -> print',
        '图标 -> router', '图标 -> pages',
        '图标 -> zoom_out_map', '图标 -> zoom_out',
        '图标 -> youtube_searched_for', '图标 -> wifi_tethering',
        '图标 -> wifi_lock', '图标 -> widgets',
        '图标 -> weekend', '图标 -> web',
        '图标 -> accessible', '图标 -> ac_unit',
    ];
    
    List<Icon> iconItems = <Icon>[
        new Icon(Icons.keyboard), new Icon(Icons.print),
        new Icon(Icons.router), new Icon(Icons.pages),
        new Icon(Icons.zoom_out_map), new Icon(Icons.zoom_out),
        new Icon(Icons.youtube_searched_for), new Icon(Icons.wifi_tethering),
        new Icon(Icons.wifi_lock), new Icon(Icons.widgets),
        new Icon(Icons.weekend), new Icon(Icons.web),
        new Icon(Icons.accessible), new Icon(Icons.ac_unit),
    ];
    
    Widget buildListData(BuildContext context, String strItem, Icon iconItem) {
        return new ListTile(
          isThreeLine: false,
          leading: iconItem,
          title: new Text(strItem),
          trailing: new Icon(Icons.keyboard_arrow_right),
          onTap: () {
            showDialog(
              context: context,
              builder: (BuildContext context) {
                return new AlertDialog(
                  title: new Text(
                    'ListViewDemo',
                    style: new TextStyle(
                      color: Colors.black54,
                      fontSize: 18.0,
                    ),
                  ),
                  content: new Text('您选择的item内容为:$strItem'),
                );
              },
            );
          },
        );
    }

    1. 默认 List

          小菜理解默认 List 方式,是把数据 Iterable 添加到列表中,之后直接添加到 ListView 即可;如下:

    List<Widget> _list = new List();
    for (int i = 0; i < strItems.length; i++) {
        _list.add(buildListData(context, strItems[i], iconItems[i]));
    }
    // 添加分割线
    var divideList =
            ListTile.divideTiles(context: context, tiles: _list).toList();
    body: new Scrollbar(
        child: new ListView(
            // 添加ListView控件
    //        children: _list,    // 无分割线
            children: divideList, // 添加分割线
        ),
    );

          Tips: 如果需要设置分割线,需要对列表 item 添加处理,ListTile.divideTiles

    2. ListView.builder

          小菜理解 builder 方式很像对话框类型逐个添加需要的属性;需要在 builder 中添加列表数据;而添加分割线的方式更让小菜体会到 Flutter 一切都是 widget 思想的重要性,如下:

    // 没有分割线
    child: new ListView.builder(
        itemCount: iconItems.length,  // 数据长度
        itemBuilder: (context, item) {
            return buildListData(context, strItems[item], iconItems[item]);
        },
    ),
    
    // 添加分割线
    child: new ListView.builder(
        itemCount: iconItems.length,
        itemBuilder: (context, item) {
            return new Container(
                child: new Column(
                  children: <Widget>[
                    buildListData(context, strItems[item], iconItems[item]),
                    new Divider()
                  ],
                ),
            );
        },
    ),

    3. ListView.separated

          小菜对 separated 方式最大的理解是有直接的分隔符设置方式,对分隔符列表应用更实用;设置 separatorBuilder 属性即可;如下:

    child: new ListView.separated(
        itemCount: iconItems.length,
        separatorBuilder: (BuildContext context, int index) => new Divider(),  // 添加分割线
        itemBuilder: (context, item) {
            return buildListData(context, strItems[item], iconItems[item]);
        },
    ),

    4. ListView.custom

          小菜暂时不对本加载方式做实例尝试,小菜理解 ListView.custom 更适合对 item 中含有子类 item,并对子类 item 的显隐性有更多操作时使用该方式更好;在以后的尝试中小菜会单独对这种方式进行测试整理。

    主要源码

    List<Widget> _list = new List();
    
    @override
    Widget build(BuildContext context) {
        for (int i = 0; i < strItems.length; i++) {
          _list.add(buildListData(context, strItems[i], iconItems[i]));
        }
        var divideList =
            ListTile.divideTiles(context: context, tiles: _list).toList();
        return new Scaffold(
          body: new Scrollbar(
            // 默认方式 List
    //        child: new ListView(
    //          children: divideList, //添加ListView控件
    //        ),
            // ListView.separated 方式
    //        child: new ListView.separated(
    //          itemCount: iconItems.length,
    //          separatorBuilder: (BuildContext context, int index) => new Divider(),
    //          itemBuilder: (context, item) {
    //            return buildListData(context, strItems[item], iconItems[item]);
    //          },
    //        ),
            // ListView.builder 方式
            child: new ListView.builder(
              itemCount: iconItems.length,
              itemBuilder: (context, item) {
                return new Container(
                  child: new Column(
                    children: <Widget>[
                      buildListData(context, strItems[item], iconItems[item]),
                      new Divider()
                    ],
                  ),
                );
              },
            ),
    //        child: new ListView.custom(
    //
    //        ),
          ),
        );
    }

          Tips: 列表中有一个属性很有意思:reverse 是否反转,如果设为 true,列表默认滑倒底部而且数据也是倒叙排列;若设为 false,则一切正常。其他很多属性也很有特点,小菜还没来得及深入探究。

          GitHub Demo

  • 相关阅读:
    自定义View的ToolBar布局报错Error:(2) No resource identifier found for attribute 'context' in package 'c
    在学git之主分支 branch
    获取发布版SHA1
    关于开启线程与UI的操作
    播放音频和视频(VideoView控件)
    通知栏Notification的应用
    Android 真机调式 Installation failed with message 远程主机强迫关闭了一个现有的连接。. It is possible that this issue is resolved by uninstalling an existing version of the apk if it is present, and then re-installing. WA
    运行程序申请危险权限
    mysql乐观锁总结和实践
    Nginx配置文件nginx.conf中文详解
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/10131805.html
Copyright © 2011-2022 走看看