Flutter使用官方CustomScrollView实现复杂页面下拉刷新和加载更多

Flutter 中官方提供CustomScrollView,让我们能够作何Appbar折叠的效果,并且很容易就能实现下拉刷新和加载更多。

class ScrollableDemoState extends State<ScrollableDemo> {
ScrollController _controller;
int _count = 10;
bool _isLoding = false;
bool _isRefreshing = false;
String loadingText = "加载中.....";

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

@override
void dispose() {
super.dispose();
_controller.dispose();
}

@override
Widget build(BuildContext context) {
return new MaterialApp(
  home: Scaffold(
    body: new Container(
      child: new NotificationListener(
        onNotification: (notification) {
          if (notification is ScrollUpdateNotification &&
              notification.depth == 0 &&
              !_isLoding &&
              !_isRefreshing) {
            if (notification.metrics.pixels ==
                notification.metrics.maxScrollExtent) {
              setState(() {
                _isLoding = true;
                loadingText = "加载中.....";
                _count += 10;
              });
              _RrefreshPull().then((value) {
                print('加载成功.............');
                setState(() {
                  _isLoding = false;
                });
              }).catchError((error) {
                print('failed');
                setState(() {
                  _isLoding = true;
                  loadingText = "加载失败.....";
                });
              });
            }
          }
        },
        child: RefreshIndicator(
          child: CustomScrollView(
            controller: _controller,
            physics: ScrollPhysics(),
            slivers: <Widget>[
              const SliverAppBar(
                pinned: true,
                title: const Text('复杂布局'),
//                    expandedHeight: 150.0,
//                    flexibleSpace: FlexibleSpaceBar(
//                      collapseMode: CollapseMode.parallax,
//                      title: Text(
//                        '复杂布局',
//                        style: TextStyle(fontSize: 16),
//                      ),
//                    ),
                elevation: 10,
                leading: Icon(Icons.arrow_back),
              ),
              SliverToBoxAdapter(
                child: Container(
                  height: 200,
                  child: new Swiper(
                    itemBuilder: (BuildContext context, int index) {
                      return new Image.network(
                        "http://pic37.nipic.com/20140113/8800276_184927469000_2.png",
                        fit: BoxFit.fill,
                      );
                    },
                    itemCount: 3,
                    pagination: new SwiperPagination(),
                  ),
                ),
              ),
              new SliverToBoxAdapter(
                child: new Container(
                  padding: EdgeInsets.only(top: 10, bottom: 10),
                  child: new Column(
                    children: <Widget>[
                      new SizedBox(
                          child: new Text(
                        'SliverGrid',
                        style: new TextStyle(fontSize: 16),
                      )),
                      new Divider(
                        color: Colors.grey,
                        height: 20,
                      )
                    ],
                  ),
                ),
              ),
              SliverGrid(
                gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                  maxCrossAxisExtent: 200.0,
                  mainAxisSpacing: 10.0,
                  crossAxisSpacing: 10.0,
                  childAspectRatio: 4.0,
                ),
                delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                    return Container(
                      alignment: Alignment.center,
                      color: Colors.teal[100 * (index % 9)],
                      child: Text('SliverGrid item $index'),
                    );
                  },
                  childCount: _count,
                ),
              ),
              new SliverToBoxAdapter(
                  child: new Container(
                padding: EdgeInsets.only(top: 10, bottom: 10),
                color: Colors.green,
                child: new SizedBox(
                    child: new Text(
                  'SliverFixedExtentList',
                  style: new TextStyle(fontSize: 16),
                )),
              )),
              SliverFixedExtentList(
                itemExtent: 50.0,
                delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                    return Container(
                      alignment: Alignment.center,
                      color: Colors.lightBlue[100 * (index % 9)],
                      child: Text('SliverFixedExtentList item $index'),
                    );
                  },
                  childCount: _count + 20,
                ),
              ),
              new SliverToBoxAdapter(
                  child: new Container(
                padding: EdgeInsets.only(top: 10, bottom: 10),
                color: Colors.green,
                child: new SizedBox(
                    child: new Text(
                  'SliverGrid',
                  style: new TextStyle(fontSize: 16),
                )),
              )),
              SliverGrid(
                gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                  maxCrossAxisExtent: 200.0,
                  mainAxisSpacing: 10.0,
                  crossAxisSpacing: 10.0,
                  childAspectRatio: 4.0,
                ),
                delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                    return Container(
                      alignment: Alignment.center,
                      color: Colors.teal[100 * (index % 9)],
                      child: Text('SliverGrid item2 $index'),
                    );
                  },
                  childCount: _count + 10,
                ),
              ),
              new SliverToBoxAdapter(
                child: new Visibility(
                  child: new Container(
                    padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
                    child: new Center(
                      child: new Text(loadingText),
                    ),
                  ),
                  visible: _isLoding,
                ),
              ),
            ],
          ),
          onRefresh: () {
            if (_isLoding) return null;
            return _RrefreshPull().then((value) {
              print('success');
              setState(() {
                _count += 10;
              });
            }).catchError((error) {
              print('failed');
            });
          },
        ),
      ),
    ),
  ),
);
}

Future<String> _RrefreshPull() async {
await Future.delayed(new Duration(seconds: 3));
return "_RrefreshPull";
}
}

class ScrollableDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return ScrollableDemoState();
 }
}

实现这些效果在Android中确实要废些时间,但是如果在Flutter中那是分分钟的事,在Flutter中提供了 Sliver族,包含:

  • SliverAppBar:
    实现AppBar的,可以折叠凳=等效果,而且是仅仅配置一个属性就行了。

  • SliverGrid和SliverFixedExtentList:
    见名思议,就是实现网格布局和列表的,没什么好说。

  • SliverToBoxAdapter:
    在CustomScrollView中直接child只能使用Sliver族的widget,如果你要使用其他的就error,所以你需要它SliverToBoxAdapter,注意一定要在外层包裹一层容器组件。

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

推荐阅读更多精彩内容