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

  • 相关阅读:
    Python-异常处理
    进程及其状态
    操作系统基础
    计算机组成基础
    Java wait()、notify()、notifyAll()方法
    Java 死锁
    线程同步
    Java 创建多线程
    Java 接口
    抽象类和抽象方法
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/10131805.html
Copyright © 2011-2022 走看看