Flutter實(shí)戰(zhàn) CustomScrollView

2021-03-08 11:30 更新

CustomScrollView是可以使用 Sliver 來(lái)自定義滾動(dòng)模型(效果)的組件。它可以包含多種滾動(dòng)模型,舉個(gè)例子,假設(shè)有一個(gè)頁(yè)面,頂部需要一個(gè)GridView,底部需要一個(gè)ListView,而要求整個(gè)頁(yè)面的滑動(dòng)效果是統(tǒng)一的,即它們看起來(lái)是一個(gè)整體。如果使用GridView+ListView來(lái)實(shí)現(xiàn)的話,就不能保證一致的滑動(dòng)效果,因?yàn)樗鼈兊臐L動(dòng)效果是分離的,所以這時(shí)就需要一個(gè)"膠水",把這些彼此獨(dú)立的可滾動(dòng)組件"粘"起來(lái),而CustomScrollView的功能就相當(dāng)于“膠水”。

#可滾動(dòng)組件的Sliver版

Sliver 在前面講過(guò),有細(xì)片、薄片之意,在 Flutter 中,Sliver 通常指可滾動(dòng)組件子元素(就像一個(gè)個(gè)薄片一樣)。但是在CustomScrollView中,需要粘起來(lái)的可滾動(dòng)組件就是CustomScrollView的Sliver了,如果直接將ListView、GridView作為CustomScrollView是不行的,因?yàn)樗鼈儽旧硎强蓾L動(dòng)組件而并不是 Sliver!因此,為了能讓可滾動(dòng)組件能和CustomScrollView配合使用,F(xiàn)lutter 提供了一些可滾動(dòng)組件的 Sliver 版,如 SliverList、SliverGrid 等。實(shí)際上 Sliver 版的可滾動(dòng)組件和非Sliver版的可滾動(dòng)組件最大的區(qū)別就是前者不包含滾動(dòng)模型(自身不能再滾動(dòng)),而后者包含滾動(dòng)模型 ,也正因如此,CustomScrollView才可以將多個(gè) Sliver"粘"在一起,這些 Sliver 共用CustomScrollViewScrollable,所以最終才實(shí)現(xiàn)了統(tǒng)一的滑動(dòng)效果。

Sliver 系列 Widget 比較多,我們不會(huì)一一介紹,讀者只需記住它的特點(diǎn),需要時(shí)再去查看文檔即可。上面之所以說(shuō)“大多數(shù)”Sliver 都和可滾動(dòng)組件對(duì)應(yīng),是由于還有一些如 SliverPadding、 SliverAppBar 等是和可滾動(dòng)組件無(wú)關(guān)的,它們主要是為了結(jié)合 CustomScrollView 一起使用,這是因?yàn)?strong>CustomScrollView 的子組件必須都是 Sliver。

#示例

  1. import 'package:flutter/material.dart';
  2. class CustomScrollViewTestRoute extends StatelessWidget {
  3. @override
  4. Widget build(BuildContext context) {
  5. //因?yàn)楸韭酚蓻](méi)有使用Scaffold,為了讓子級(jí)Widget(如Text)使用
  6. //Material Design 默認(rèn)的樣式風(fēng)格,我們使用Material作為本路由的根。
  7. return Material(
  8. child: CustomScrollView(
  9. slivers: <Widget>[
  10. //AppBar,包含一個(gè)導(dǎo)航欄
  11. SliverAppBar(
  12. pinned: true,
  13. expandedHeight: 250.0,
  14. flexibleSpace: FlexibleSpaceBar(
  15. title: const Text('Demo'),
  16. background: Image.asset(
  17. "./images/avatar.png", fit: BoxFit.cover,),
  18. ),
  19. ),
  20. SliverPadding(
  21. padding: const EdgeInsets.all(8.0),
  22. sliver: new SliverGrid( //Grid
  23. gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
  24. crossAxisCount: 2, //Grid按兩列顯示
  25. mainAxisSpacing: 10.0,
  26. crossAxisSpacing: 10.0,
  27. childAspectRatio: 4.0,
  28. ),
  29. delegate: new SliverChildBuilderDelegate(
  30. (BuildContext context, int index) {
  31. //創(chuàng)建子widget
  32. return new Container(
  33. alignment: Alignment.center,
  34. color: Colors.cyan[100 * (index % 9)],
  35. child: new Text('grid item $index'),
  36. );
  37. },
  38. childCount: 20,
  39. ),
  40. ),
  41. ),
  42. //List
  43. new SliverFixedExtentList(
  44. itemExtent: 50.0,
  45. delegate: new SliverChildBuilderDelegate(
  46. (BuildContext context, int index) {
  47. //創(chuàng)建列表項(xiàng)
  48. return new Container(
  49. alignment: Alignment.center,
  50. color: Colors.lightBlue[100 * (index % 9)],
  51. child: new Text('list item $index'),
  52. );
  53. },
  54. childCount: 50 //50個(gè)列表項(xiàng)
  55. ),
  56. ),
  57. ],
  58. ),
  59. );
  60. }
  61. }

代碼分為三部分:

  • 頭部SliverAppBarSliverAppBar對(duì)應(yīng)AppBar,兩者不同之處在于SliverAppBar可以集成到CustomScrollView。SliverAppBar可以結(jié)合FlexibleSpaceBar實(shí)現(xiàn) Material Design 中頭部伸縮的模型,具體效果,讀者可以運(yùn)行該示例查看。
  • 中間的SliverGrid:它用SliverPadding包裹以給SliverGrid添加補(bǔ)白。SliverGrid是一個(gè)兩列,寬高比為4的網(wǎng)格,它有20個(gè)子組件。
  • 底部SliverFixedExtentList:它是一個(gè)所有子元素高度都為50像素的列表。

運(yùn)行效果如圖:

圖6-12

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)