Flutter ListView


简介

ListView “滚动列表”

  • 一个非常常用的控件,涉及到数据列表展示的,一般情况下都会选用该控件。
  • 跟GridView相似,基本上是一个slivers里面只包含一个SliverList的CustomScrollView。

基本用法

布局行为

  • ListView在主轴方向可以滚动,在交叉轴方向,则是填满ListView。
  • 一个组合控件。ListView跟GridView类似,都是继承自BoxScrollView。
  • 在Flutter中有几种构建ListView的方式,分别是: 默认List,ListView.builder, ListView.separated,ListView.custom

ListView()

  • 默认 List 方式,是把数据 Iterable 添加到列表中,之后直接添加到 ListView 即可。
  • Tips: 如果需要设置分割线,需要对列表 item 添加处理,ListTile.divideTiles。
  • 仅适用于内容较少的情形,因为它是一次性渲染所有的 items ,当 items 的数目较多时,很容易出现卡顿现象的,导致滑动不流畅。

ListView.builder()

  • 设置单个item的属性,懒加载的,假如有 1000 个列表,初始渲染时并不会所有都渲染,而只会特定数量的 item ,这对于性能和用户体验来说,是很好的提升。

官方示例 ListView.separated()

  • 带分割线的item,separated 相比较于 builder,又多了一个参数 separatorBuilder ,用于控制列表各个元素的间隔如何渲染。

官方示例 ListView.custom()

  • 必须的参数就是 childrenDelegate , 然后传入一个 实现了 SliverChildDelegate 的组件,如 SliverChildListDelegate 和 SliverChildBuilderDelegate。

实例演示

import 'package:flutter/material.dart';

/*
* ListView 默认ListView的实例
* */
class ListViewFullDefault extends StatefulWidget {
  const ListViewFullDefault() : super();

  @override
  State<StatefulWidget> createState() => _ListViewFullDefault();
}

/*
* ListView 默认的实例,有状态
* */
class _ListViewFullDefault extends State {
  @override
  Widget build(BuildContext context) {
    return ListView(
    );
  }
}

/*
* ListView 默认的实例,无状态
* */
class ListViewLessDefault extends StatelessWidget {
  final widget;
  final parent;
  final index;

  const ListViewLessDefault([this.index, this.widget, this.parent,])
      : super();

  @override
  Widget build(BuildContext context) {
    switch(index){
      case 0:
        return ListView(
          shrinkWrap: true,
          padding: EdgeInsets.all(20.0),
          children: <Widget>[
            Text('I\'m dedicating every day to you'),
            ListTile(
              leading:  Icon(Icons.map),
              title:  Text('Maps'),
            ),
            Text('Domestic life was never quite my style'),
            ListTile(
              leading:  Icon(Icons.photo_album),
              title:  Text('Album'),
            ),
            Text('When you smile, you knock me out, I fall apart'),
            ListTile(
              leading:  Icon(Icons.phone),
              title:  Text('Phone'),
            ),
            Text('And I thought I was so smart'),
          ],
        );
        break;
      case 1:
        return SizedBox(
          height: 300.0,
          child:  ListView.builder(
            scrollDirection: Axis.vertical,
            itemCount: 10, // item 的个数
            itemExtent: 50.0, // 如果为非null,则强制子项在滚动方向上具有给定范围
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                  title:  Text("title $index"), // item 标题
                  leading: Icon(Icons.keyboard), // item 前置图标
                  subtitle: Text("subtitle $index"), // item 副标题
                  trailing: Icon(Icons.keyboard_arrow_right),// item 后置图标
                  isThreeLine:false,  // item 是否三行显示
                  dense:true,                // item 直观感受是整体大小
                  contentPadding: EdgeInsets.all(10.0),// item 内容内边距
                  enabled:true,
                  onTap:(){print('点击:$index');},// item onTap 点击事件
                  onLongPress:(){print('长按:$index');},// item onLongPress 长按事件
                  selected:false,     // item 是否选中状态
              );
            },
          ),
        );
        break;
      case 2:
        return SizedBox(
          height: 300.0,
          child:  ListView.separated(
            scrollDirection: Axis.vertical,
            itemCount: 100, // item 的个数
            separatorBuilder: (BuildContext context, int index) => Divider(height:1.0,color: Colors.blue),  // 添加分割线
            itemBuilder: (BuildContext context, int index) {
              return ListTile(
                title:  Text("title $index"), // item 标题
                leading: Icon(Icons.keyboard), // item 前置图标
                subtitle: Text("subtitle $index"), // item 副标题
                trailing: Icon(Icons.keyboard_arrow_right),// item 后置图标
                isThreeLine:false,  // item 是否三行显示
                dense:true,                // item 直观感受是整体大小
                contentPadding: EdgeInsets.all(10.0),// item 内容内边距
                enabled:true,
                onTap:(){print('点击:$index');},// item onTap 点击事件
                onLongPress:(){print('长按:$index');},// item onLongPress 长按事件
                selected:false,     // item 是否选中状态
              );
            },
          ),
        );
      break;
      case 3:
        return SizedBox(
          height: 300.0,
          child:  ListView.custom(
            scrollDirection: Axis.vertical,
            childrenDelegate:SliverChildBuilderDelegate((BuildContext context, int index) {
              return Container(
                height: 50.0,
                alignment: Alignment.center,
                color: Colors.lightBlue[100 * (index % 9)],
                child: Text('list item $index'),
              );
            }, childCount: 10),
          ),
        );
        break;
      default:
        return null;
        break;
    }
  }
}