Flutter 滑動列表組件 ListView&&GridView

這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰緩存

相關文章:Flutter listview下拉刷新 上拉加載更多 (juejin.cn)markdown

#前言: 今天就來介紹下Flutter中的列表組件ListView和網格組件GirdView,嗯,果真是Google家的親兒子,連名字都和Android裏的如出一轍。 好的吧,咱們仍是來看下這兩個Widget的用法吧app


#ListView ListView就是咱們常見的列表組件,在平時的應用開發中十分的常見,不管你作的是什麼類型的應用都會多多少少會用到ListView,因此要好好看下這篇文章哦less

仍是先來看下listView的構造方法:ide

ListView({
Key key,
Axis scrollDirection: Axis.vertical,//滾動方向
bool reverse: false,//是否反向顯示數據
ScrollController controller,
bool primary,
ScrollPhysics physics,//物理滾動
bool shrinkWrap: false,
EdgeInsetsGeometry padding,
this.itemExtent,//item有效範圍
bool addAutomaticKeepAlives: true,//自動保存視圖緩存
bool addRepaintBoundaries: true,//添加劇繪邊界
List<Widget> children: const <Widget>[],
})
複製代碼

那麼,咱們仍是來看下具體的用法oop

咱們仍是按照慣例在Scaffold裏放一個ListViewpost

import 'package:flutter/material.dart';

class Routes extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('目錄')),
      body: new ListView(
        children: <Widget>[
          ListTile(
            title: Text('標題1'),
            leading: Icon(Icons.build),
            trailing: Text('尾巴'),
            onTap: () {
              showDialog(
                  context: context,
                  child: new SimpleDialog(
                    contentPadding: const EdgeInsets.all(10.0),
                    title: new Text("我是標題"),
                    children: <Widget>[new Text("我是內容區域")],
                  ));
            },
          ),
          ListTile(
            title: Text('標題2'),
            leading: Icon(Icons.print),
            trailing: Text('尾巴'),
          ),
          ListTile(
            title: Text('標題3'),
            leading: Icon(Icons.library_music),
            trailing: Text('尾巴'),
          ),
          ListTile(
            title: Text('標題4'),
            leading: Icon(Icons.accessibility_new),
            trailing: Text('尾巴'),
          ),
        ],
      ),
    );
  }
}

複製代碼

children參數咱們傳入了4個ListTile,先介紹下: ListTile是一個固定高度的行,一般包含一些文本,以及一個行前或行尾圖標。測試

const ListTile({
    Key key,
    this.leading,
    this.title,
    this.subtitle,
    this.trailing,
    this.isThreeLine = false,
    this.dense,
    this.contentPadding,
    this.enabled = true,
    this.onTap,
    this.onLongPress,
    this.selected = false,
  }) : assert(isThreeLine != null),
       assert(enabled != null),
       assert(selected != null),
       assert(!isThreeLine || subtitle != null),
       super(key: key);
       
複製代碼

而後咱們來看下效果 ![這裏寫圖片描述] (img-blog.csdn.net/20180905161…)ui

固然,因爲數據量過少它如今是不能滑動的。你們能夠在下面多加幾個Widget試試效果。this

在Flutter中有三種構建ListView的方式,剛纔介紹的是最簡單的一種,可是卻不是最經常使用的,由於它僅僅適用於已知數量或者較少數量的Item的狀況。若是有未知數量或者無限個Item的狀況,再使用上述的方法將再也不適用。

那麼,咱們能夠嘗試下ListView.builder()ListView.custom()

ListView.builder()和ListView.custom()的用法基本相同,只不過custom能夠根據本身的須要控制Item顯示方式,如Item顯示大小。

咱們今天來看下ListView.builder()

ListView.builder({
    Key key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController controller,
    bool primary,
    ScrollPhysics physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry padding,
    this.itemExtent,
    @required IndexedWidgetBuilder itemBuilder,         //item構建者
    int itemCount,                                     //item數量
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    double cacheExtent,
  }) 
複製代碼

相比於new ListView()只不過多出了兩個參數而已,一個是itemCount指定item的數量,一個是itemBuilder,用來構建Item。

看下用法

import 'package:flutter/material.dart';

class ListItem {
  final String title;
  final IconData iconData;

  ListItem(this.title, this.iconData);
}

class ListItemWidget extends StatelessWidget {
  final ListItem listItem;

  ListItemWidget(this.listItem);

  @override
  Widget build(BuildContext context) {
    return new ListTile(
      leading: new Icon(listItem.iconData),
      title: new Text(listItem.title),
    );
  }
}

class Routes extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return RouteState();
  }
}

class RouteState extends State<Routes> {
  final List<ListItem> listData = [];

  @override
  void initState() {
    super.initState();
    for (int i = 0; i < 20; i++) {
      listData.add(ListItem("我是測試標題$i", Icons.cake));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('列表'),
      ),
      body: ListView.builder(
        itemBuilder: (BuildContext context, int index) {
          return ListItemWidget(listData[index]);
        },
        itemCount: listData.length,
      ),
    );
  }
}
複製代碼

咱們首先新建了一個ListItem對象,icon和title兩個屬性 咱們新建了一個一個Widget,須要傳入ListItem對象,藉助於ListItem對象的屬性初始化ListTitle。 而後在initState方法中初始化listData,建立了20個ListItem對象。

在itemBuilder中返回指定的的Listitem到ListItemWidget對象中,返回指定的ListItemWidget對象。

經過這種方法,咱們不須要關注Item的數量,由於咱們每一個Item都是自動構建的,而且大大減小重複代碼的數量。 這裏寫圖片描述 下面來看下GridView


#GridView GirView的用法和ListView相似,只不過因爲GridView能夠在一列或者一行顯示多個Item,因此在構造方法中就多了個參數

GridView({
    Key key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController controller,
    bool primary,
    ScrollPhysics physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry padding,
    @required this.gridDelegate,        //沒錯,它就是控制GridView的
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    double cacheExtent,
    List<Widget> children = const <Widget>[],
  })
  
複製代碼

看下gridDelegate參數

能夠傳入SliverGridDelegateWithFixedCrossAxisCount對象和SliverGridDelegateWithMaxCrossAxisExtent對象。 其中SliverGridDelegateWithFixedCrossAxisCount能夠直接指定每行(列)顯示多少個Item,SliverGridDelegateWithMaxCrossAxisExtent會根據GridView的寬度和你設置的每一個的寬度來自動計算沒行顯示多少個Item 國際慣例,咱們仍是隻介紹一個,那就SliverGridDelegateWithFixedCrossAxisCount吧。

看下代碼,怎麼用

import 'package:flutter/material.dart';

class GridViewPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GridView'),
      ),
      body: GridView(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2, //每行2個
            mainAxisSpacing: 10.0, //主軸(豎直)方向間距
            crossAxisSpacing: 10.0, //縱軸(水平)方向間距
            childAspectRatio: 1.0 //縱軸縮放比例
            ),
        children: <Widget>[
          Container(
            alignment: Alignment.center,
            color: Colors.green,
            child: Image.asset("images/pic1.jpg"),
          ),
          Container(
            alignment: Alignment.center,
            color: Colors.green,
            child: Image.asset("images/pic1.jpg"),
          ),
          Container(
            alignment: Alignment.center,
            color: Colors.green,
            child: Image.asset("images/pic1.jpg"),
          ),
          Container(
            alignment: Alignment.center,
            color: Colors.green,
            child: Image.asset("images/pic1.jpg"),
          ),
          Container(
            alignment: Alignment.center,
            color: Colors.green,
            child: Image.asset("images/pic1.jpg"),
          ),
          Container(
            alignment: Alignment.center,
            color: Colors.green,
            child: Image.asset("images/pic1.jpg"),
          ),
          Container(
            alignment: Alignment.center,
            color: Colors.green,
            child: Image.asset("images/pic1.jpg"),
          ),
        ],
      ),
    );
  }
}

複製代碼

和ListView相似,咱們在GridView的children中新增了7個圖片並給它設置背景並居中,另外咱們根據gridDelegate屬性設置每行顯示2個Item,而且設置Item間隔爲10像素。

效果以下: 這裏寫圖片描述 固然,GridView你也可使用builder()和custom()的方式實現

import 'package:flutter/material.dart';

class GridViewPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return GridViewState();
  }
}

class GridViewState extends State<GridViewPage> {
  final List<ListItem> listData = [];

  @override
  void initState() {
    super.initState();
    for (int i = 0; i < 20; i++) {
      listData.add(new ListItem("我是測試標題$i", Icons.cake));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GridView'),
      ),
      body: GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 2, //每行2個
            mainAxisSpacing: 10.0, //主軸(豎直)方向間距
            crossAxisSpacing: 10.0, //縱軸(水平)方向間距
            childAspectRatio: 1.0 //縱軸縮放比例
            ),
        itemCount: listData.length,
        itemBuilder: (BuildContext context, int index) {
          return ListItemWidget(listData[index]);
        },
      ),
    );
  }
}

class ListItem {
  final String title;
  final IconData iconData;

  ListItem(this.title, this.iconData);
}

class ListItemWidget extends StatelessWidget {
  final ListItem listItem;

  ListItemWidget(this.listItem);

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      child: new Container(
        color: Colors.green,
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Icon(
              listItem.iconData,
              size: 50.0,
              color: Colors.white,
            ),
            new Text(
              listItem.title,
              style: TextStyle(color: Colors.white),
            )
          ],
        ),
      ),
      onTap: () {
        Scaffold.of(context).showSnackBar(new SnackBar(
          content: new Text(listItem.title),
        ));
      },
    );
  }
}

複製代碼

和上面ListView的用相似,只不過咱們如今是一行顯示多個Item而已。而且咱們給每一個Item設置上了點擊事件,每次點擊Item就會彈出相應的標題。 這裏寫圖片描述


##小結

  • ListView就是咱們經常使用的列表視圖

  • GridView就是咱們經常使用的宮格視圖

  • ListView和GridView均可以使用new 或者builder()和custom()方法來建立對象

相關文章
相關標籤/搜索