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閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件系宫,死亡現場離奇詭異索昂,居然都是意外死亡,警方通過查閱死者的電腦和手機扩借,發(fā)現死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門椒惨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人潮罪,你說我怎么就攤上這事框产。” “怎么了错洁?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長戒突。 經常有香客問我屯碴,道長,這世上最難降的妖魔是什么膊存? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任导而,我火速辦了婚禮,結果婚禮上隔崎,老公的妹妹穿的比我還像新娘今艺。我一直安慰自己,他們只是感情好爵卒,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布虚缎。 她就那樣靜靜地躺著,像睡著了一般钓株。 火紅的嫁衣襯著肌膚如雪实牡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天轴合,我揣著相機與錄音创坞,去河邊找鬼。 笑死受葛,一個胖子當著我的面吹牛题涨,可吹牛的內容都是我干的。 我是一名探鬼主播总滩,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼纲堵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了咳秉?” 一聲冷哼從身側響起婉支,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎澜建,沒想到半個月后向挖,有當地人在樹林里發(fā)現了一具尸體蝌以,經...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年何之,在試婚紗的時候發(fā)現自己被綠了跟畅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡溶推,死狀恐怖徊件,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情蒜危,我是刑警寧澤虱痕,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站辐赞,受9級特大地震影響部翘,放射性物質發(fā)生泄漏。R本人自食惡果不足惜响委,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一新思、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赘风,春花似錦夹囚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞬捕,卻和暖如春敲茄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背山析。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工堰燎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人笋轨。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓秆剪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親爵政。 傳聞我的和親對象是個殘疾皇子仅讽,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容