Flutter 滾動列表 ListView 圖文示例

ListView、ListView.builder

這是ListView的兩個構造函數,ListView構造函數在列表佈局少的時候使用,ListView.builder在渲染列表數據多的時候有優勢。

  ListView({
    Key key,
    Axis scrollDirection = Axis.vertical,//設置滑動方向 Axis.horizontal 水平  默認 Axis.vertical 垂直
    bool reverse = false,//是否倒序顯示 默認正序 false  倒序true
    ScrollController controller,//滑動監聽
    bool primary,//false,如果內容不足,則用戶無法滾動 而如果[primary]爲true,它們總是可以嘗試滾動。
    ScrollPhysics physics,//列表滾動至邊緣後繼續拖動的物理效果
    bool shrinkWrap = false,//child 高度會適配 item填充的內容的高度,
    EdgeInsetsGeometry padding,// 列表內邊距
    this.itemExtent,//確定每一個item的高度 會讓item加載更加高效
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double cacheExtent,//cacheExtent  設置預加載的區域
    List<Widget> children = const <Widget>[],// 列表內容
    int semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  })

ListView.builder 的構造函數基本和 ListView 一致,僅多了個字段 int itemCount, 表示列表數據的數量

ListView 使用

在這裏插入圖片描述

Widget _buildListView() {

      return ListView(
        scrollDirection: Axis.horizontal,
        itemExtent: 140, //item延展尺寸(寬度)
        children: [
          //設置ListTile組件的標題與圖標
          ListTile(leading: Icon(Icons.map), title: Text('Map')),
          ListTile(leading: Icon(Icons.mail), title: Text('Mail')),
          ListTile(leading: Icon(Icons.message), title: Text('Message')),
        ]
      );
    }

ListView.builder 使用

在這裏插入圖片描述

 ListView.builder(
          itemCount: 100,// 100 條數據
          itemExtent: 50.0,// 每條數據的高度是50
          itemBuilder: (BuildContext context, int index) {
           // 每條數據使用 ListTile 渲染
            return ListTile(title: Text("$index"));
          }
      );

ListTile

ListTileFlutter 提供的widget ,通過查看參數去了解這個widget能實現哪些功能。

  const ListTile({
    Key key,
    this.leading,// item 前置圖標
    this.title, // item 標題
    this.subtitle,// item 副標題
    this.trailing,// item 後置圖標
    this.isThreeLine = false,// item 是否三行顯示
    this.dense,
    this.contentPadding,// item 內容內邊距
    this.enabled = true,// item 是否可用
    this.onTap,// item onTap 點擊事件
    this.onLongPress,// item onLongPress 長按事件
    this.selected = false,// item 是否選中狀態
  })

在這裏插入圖片描述
僞代碼如下:

ListView.builder(
    itemCount: 100,
    itemExtent: 50.0,
    itemBuilder: (BuildContext context, int index) {
      return ListTile(
          title: Text("$index"),
        subtitle: Text("subtitle $index"),
        leading: Icon(Icons.favorite),
        trailing: Icon(Icons.delete),
      );
    }
);

ListView.separated 分割線

在列表中經常會增加分割線來區分每一個 Item區域,在Flutter中也提供了ListView.separated構造方法實現。

效果圖:分割線高度爲5 ,且 index 爲偶數, 創建綠色分割線,index爲奇數, 則創建紅色分割線

在這裏插入圖片描述

ListView.separated(
    itemCount: 100,
    //分割器構造器,高度爲5 ,index 爲偶數, 創建綠色分割線, index爲奇數, 則創建紅色分割線
    separatorBuilder: (BuildContext context, int index){
      return index %2 == 0 ? Divider(thickness:5.0, color: Colors.green) : Divider(thickness:5.0, color: Colors.red);
    },
    //列表項構造器
    itemBuilder: (BuildContext context, int index) {
      return ListTile(
        title: Text("$index"),
        subtitle: Text("subtitle $index"),
        leading: Icon(Icons.favorite),
        trailing: Icon(Icons.delete),
      );
    }
);

一般列表中我們都會有添加 上拉加載下拉刷新 的功能,有的頁面佈局還會增加頭部和尾部

上拉加載 的功能在ListView可以通過監聽列表滑動來實現。

下拉刷新的功能可以結合RefreshIndicator這個組件來實現。

頭部和尾部的功能主要是通過判斷ListViewitem的位置來動態添加widget,具體可參考這篇文章Flutter 之列表和頭部 (ListView + Header),或者使用CustomScrollView組件實現。

第三方庫推薦

下面僅使用flutter_easyrefresh做示例。

上下拉加載數據

在這裏插入圖片描述

  1. 引入該庫:
dependencies:
  flutter_easyrefresh: ^2.0.9
  1. 使用例子
class EasyRefreshPage extends StatefulWidget {
  @override
  _EasyRefreshPageState createState() {
    return _EasyRefreshPageState();
  }
}

class _EasyRefreshPageState extends State<EasyRefreshPage> {

  EasyRefreshController _controller;
  // 條目總數
  int _count = 20;
  // 數據已全部加載完成
  bool _enableControlFinish = false;

  @override
  void initState() {
    super.initState();
    _controller = EasyRefreshController();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        appBar: AppBar(
          title: Text('上拉加載、下拉刷新'),
        ),
        body: Center(
          child: Container(
            child: EasyRefresh.custom(
              controller: _controller,
              onRefresh:() async {
                await Future.delayed(Duration(milliseconds: 200), () {
                  if (mounted) {
                    setState(() {
                      _count = 20;
                    });
                  }
                });
              },
              onLoad:  () async {
                await Future.delayed(Duration(milliseconds: 200), () {
                  if (mounted) {
                    setState(() {
                      _count += 20;
                    });
                    // 數據全部加載完成
                    if (!_enableControlFinish) {
                      _controller.finishLoad(noMore: _count >= 40);
                    }
                  }
                });
              },
              slivers: <Widget>[
                SliverList(
                  delegate: SliverChildBuilderDelegate(
                        (context, index) {
                      return ListTile(
                        title: Text('$index'),
                      );
                    },
                    childCount: _count,
                  ),
                ),
              ],
            ),
          ),
        ),
    );
  }
}

完~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章