Flutter基础(七)Scrolling Widget之ListView、GridView、PageView

本文首发于公众号「后厂村码农」

ReactNative入门系列
React Native组件
Flutter基础系列

前言

我们知道Widget的分类有很多种,比如:Basics、Material Components、Cupertino、Scrolling等等,在前面的文章我介绍了Basics和Material Components,这一篇讲一下Scrolling分类中比较常用的ListView、GridView、PageView。

1 ListView

ListView可以说是Flutter中最常用的Scrolling Widget。
ListView有四种构造函数:

  1. 默认构造函数ListView。
  2. ListView.builder,适用于具有大量(或无限)列表项。
  3. ListView.separated,可以配置分割线,适用于具有固定数量列表项的ListView。
  4. ListView.custom,提供了自定义子Widget的能力。

1.1 默认构造函数

用默认构造函数的方式来实现一个简单的列表。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView示例'),
        ),
        body: ListView(
          children: <Widget>[
            ListTile(
              leading: Icon(Icons.access_time),
              title: Text('第1行'),
            ),
            ListTile(
              leading: Icon(Icons.access_time),
              title: Text('第2行'),
            ),
          ],
        ),
      ),
    );
  }
}

ListTile是Material Components中的Widget,通常用于填充ListView,可以满足基本的图片+文字的列表需求。

VwPmwj.png

1.2 ListView.builder创建

如果要展示大量列表项,可以使用ListView.builder。

import 'package:flutter/material.dart';

void main() => runApp(MyApp(
      items: new List<String>.generate(300, (i) => "第$i行"), //1
    ));

class MyApp extends StatelessWidget {
  final List<String> items;

  MyApp({@required this.items});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView示例'),
        ),
        body: ListView.builder( //2
          itemCount: items.length,
          itemBuilder: (context, index) {
            return ListTile(
              leading: Icon(Icons.access_time),
              title: Text('${items[index]}'),
            );
          },
        ),
      ),
    );
  }
}

在注释1生成300个数据,并将其传入到MyApp中,注释2处通过ListView.builder创建ListView,最终会通过ListTile来显示每一个列表项。


VwP86U.png

1.3 ListView.separated创建

import 'package:flutter/material.dart';

void main() => runApp(MyApp(
      items: new List<String>.generate(300, (i) => "第$i行"), 
    ));

class MyApp extends StatelessWidget {
  final List<String> items;

  MyApp({@required this.items});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Test',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView示例'),
        ),
        body: ListView.separated(
          itemCount: items.length,
          itemBuilder: (context, index) {
            return ListTile(
              leading: Icon(Icons.access_time),
              title: Text('${items[index]}'),
            );
          },
          separatorBuilder: (context, index) {//1
            return Container(
              constraints: BoxConstraints.tightFor(height: 1),
              color: Colors.black45,
            );
          },
        ),
      ),
    );
  }
}

这种创建方式和ListView.builder类似,有个最大的不同就是可以通过注释1处的separatorBuilder来设置分割线以及分割线的样式。


VwDsxA.png

2 GridView

GridView的使用方法和ListView类似,它有五种构造函数:

  1. 默认构造函数GridView。
  2. GridView.count:在横轴方向上具有固定数量的GridView。
  3. GridView.extent:在横轴方向上具有最大范围的GridView。
  4. GridView.builder:适用于具有大量(或无限)列表项。
  5. GridView.custom:提供了自定义子Widget的能力。

这里以第2种构造函数为例。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: new Text('GridView示例'),
        ),
        body: GridView.count(
          crossAxisCount: 3, //1
          children: <Widget>[
            ListTile(
              title: Text('item1'),
            ),
            ListTile(
              title: Text('item2'),
            ),
            ListTile(
              title: Text('item3'),
            ),
            ListTile(
              title: Text('item4'),
            ),
            ListTile(
              title: Text('item5'),
            ),
            ListTile(
              title: Text('item6'),
            ),
            ListTile(
              title: Text('item7'),
            ),
            ListTile(
              title: Text('item8'),
            ),
            ListTile(
              title: Text('item9'),
            ),
          ],
        ),
      ),
    );
  }
}

注释1处的crossAxisCount用于设置横轴item的数量。效果如下图所示:


VBCOyT.png

3 PageView

PageView是一个可逐页滚动的列表,和Android中ViewPage类似。
PageView有三种构造函数:

  1. 默认构造函数PageView
  2. PageView.builder:适用于具有大量(或无限)列表项。
  3. PageView.custom:提供了自定义子Widget的能力。

以默认构造函数为例,代码如下所示。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('PageView示例'),
        ),
        body: PageView(
          onPageChanged: (index) {//1
            print('当前为第 $index 页');
          },
          children: <Widget>[
            ListTile(
              title: Text('第0页'),
            ),
            ListTile(
              title: Text('第1页'),
            ),
            ListTile(
              title: Text('第2页'),
            ),
          ],
        ),
      ),
    );
  }
}

通过注释1处的onPageChanged属性可以得知当前滑动到了第几页。


VBk9Yj.png

总结

本文并没有介绍每个Widget的构造函数,那样的话就不是一篇文章能写下的了,也没有必要,我们掌握了其中一种构造函数基本就可以举一反三了。Scrolling Widget还包含了一些其他Widget,比如:NestedScrollView、Scrollbar、CustomScrollView、NotificationListener等等,就需要去自行查看官方文档了:https://flutter.dev/docs/development/ui/widgets/scrolling

更多的内容请关注我的独立博客的知识体系:
http://liuwangshu.cn/system/


这里不仅分享大前端、Android、Java等技术,还有程序员成长类文章。


image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容