Flutter CustomScrollView 自定義滑動(dòng)效果

新建項(xiàng)目-8.png

CustomScrollView

構(gòu)造函數(shù)

 const CustomScrollView({
    Key key,
    Axis scrollDirection = Axis.vertical, //滑動(dòng)的方向
    bool reverse = false, //控制 CustomScrollView 里列表項(xiàng)的排列順序
    ScrollController controller, //可以控制 CustomScrollView 滾動(dòng)的位置
                                                                     ScrollController 提供以下的幾個(gè)功能:
                                                                     1.設(shè)置 CustomScrollView 滑動(dòng)的初始位置
                                                                     2.可以控制 CustomScrollView 是否存儲(chǔ)和恢復(fù)滑動(dòng)的位置
                                                                     3.可以讀取、設(shè)置當(dāng)前滑動(dòng)的位置
                                                                     可以繼承 ScrollController 實(shí)現(xiàn)自定義的功能
                                                                     當(dāng) primary 為 true 時(shí),controller 必須為 null
    bool primary,
    ScrollPhysics physics,
    bool shrinkWrap = false,
    Key center, //放在 CustomScrollView 中間的 子Widget 的 key 
    double anchor = 0.0, //CustomScrollView 開(kāi)始滑動(dòng)的偏移量
                                                如果 anchor 為 0.0,則 CustomScrollView 的 子Widget 從頭開(kāi)始排列
                                                如果 anchor 為 0.5,則 CustomScrollView 的 子Widget 從中間開(kāi)始排列
                                                如果 anchor 為 1.0,則 CustomScrollView 的 子Widget 從底部開(kāi)始排列    
    double cacheExtent,
    this.slivers = const <Widget>[],
    int semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,//
                        確定處理拖動(dòng)開(kāi)始行為的方式。
                                                如果設(shè)置為[DragStartBehavior.start],則在檢測(cè)到拖動(dòng)手勢(shì)時(shí)將開(kāi)始滾動(dòng)拖動(dòng)行為
                                                如果設(shè)置為[DragStartBehavior.down],它將在首次檢測(cè)到向下事件時(shí)開(kāi)始   可選
  }) 

SliverAppBar

基本和AppBar一樣,只是他只能在CustomScrollView中使用,應(yīng)該很常見(jiàn),滑動(dòng)的時(shí)候固定appbar,就需要用到他.

const SliverAppBar({
    Key key,
    this.leading,                          //左上角添加組件
    this.automaticallyImplyLeading = true,
    this.title,   
    this.actions,               //右上角添加組件
    this.flexibleSpace,   //擴(kuò)展的組件
    this.bottom,          //
    this.elevation,
    this.forceElevated = false,
    this.backgroundColor,
    this.brightness,
    this.iconTheme,
    this.actionsIconTheme,
    this.textTheme,
    this.primary = true,
    this.centerTitle,
    this.titleSpacing = NavigationToolbar.kMiddleSpacing,
    this.expandedHeight,
    this.floating = false,
    this.pinned = false,
    this.snap = false,
    this.stretch = false,
    this.stretchTriggerOffset = 100.0,
    this.onStretchTrigger,
    this.shape,
  })

大部分和appbar一樣,主要說(shuō)下重要的幾個(gè):

pinned

是否將導(dǎo)航欄部分固定在appbar的位置.這個(gè)需求在實(shí)際中很常用. 看看效果圖.

當(dāng) pinned = false:

2020-04-13 17.41.58.gif

可以看到appbar并沒(méi)有固定在最上面,而是根據(jù)內(nèi)容劃出了界面.

當(dāng) pinned = true :

2020-04-13 17.43.50.gif

這個(gè)應(yīng)該是需求中經(jīng)常用到的效果了.

floating

當(dāng)floating = false :

2020-04-13 17.48.02.gif

當(dāng)floating = true:

2020-04-13 17.51.30.gif

仔細(xì)看 ,區(qū)別是在列表整體向下滑動(dòng)時(shí),appbar開(kāi)始顯示的位置不同.

當(dāng)為false時(shí),向下滑動(dòng)時(shí),會(huì)先降列表內(nèi)容滑動(dòng)頂部,然后appbar會(huì)跟著列表滑動(dòng)顯示出來(lái).如上圖

當(dāng)為true時(shí),向下滑動(dòng)時(shí),appbar會(huì)先跟著列表滑動(dòng)顯示出來(lái). 然后繼續(xù)列表的滑動(dòng). 如上圖

snap

不能單獨(dú)使用要配合 ****floating 和 ****pinned

具體效果看官網(wǎng)地址

stretch

是否展開(kāi),默認(rèn)false,直接看值為true的效果圖,就明白了.

2020-04-13 18.05.55.gif

flexibleSpace

可以再里面添加擴(kuò)展的內(nèi)容:

 flexibleSpace: FlexibleSpaceBar(
   title: Text('開(kāi)學(xué)季 Pinned 效果'),
   background: Image.network(
     "https://goss.cfp.cn/creative/vcg/800/new/VCG211165042753.jpg",
     fit: BoxFit.cover,
   ),
 ),
flexibleSpace: Row(
  children: <Widget>[
    Expanded(
      child: Image.network('https://goss.cfp.cn/creative/vcg/800/new/VCG211165042753.jpg',fit: BoxFit.cover,),
    )
  ],
),

通過(guò)測(cè)試發(fā)現(xiàn) **后面不是 FlexibleSpaceBar 的話, stretch = true 無(wú)效. **

SliverPadding

和Padding一樣.子控件是 sliver 類型...

const SliverPadding({
    Key key,
    @required this.padding,
    Widget sliver,
}) 

列子:

 SliverPadding(
   padding: EdgeInsets.only(top: 10),
   sliver: SliverToBoxAdapter(
     child: Container(
       height: 66,
       color: Colors.cyanAccent,
     ),
   ),
 ),

2020-04-13 18.28.54.gif

上圖中在padding中添加了一個(gè)背景色為青色的容器widget

SliverToBoxAdapter

const SliverToBoxAdapter({
    Key key,
    Widget child,
  })

里面可以設(shè)置不是sliver類型的widget。如上圖中的 padding中添加的 container

SliverGrid

 const SliverGrid({
    Key key,
    @required SliverChildDelegate delegate,
    @required this.gridDelegate,
  })

就兩個(gè)協(xié)議,一個(gè)是布局協(xié)議一個(gè)展示協(xié)議.基本和GridView一樣.也有count和extext... 不設(shè)置個(gè)數(shù)默認(rèn)無(wú)數(shù)個(gè)

SliverChildListDelegate 這種方式前提是知道cell個(gè)數(shù),比較少,好搭建

SliverChildBuilderDelegate 這種方式,可以根據(jù)數(shù)組去創(chuàng)建,不知道cell個(gè)數(shù)

SliverFixedExtentList

 const SliverFixedExtentList({
    Key key,
    @required SliverChildDelegate delegate,
    @required this.itemExtent,
  }) : 

和listview差不多.也是協(xié)議 不設(shè)置個(gè)數(shù)默認(rèn)無(wú)數(shù)個(gè)

例子:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class MinePage extends StatefulWidget {
  @override
  _MinePageState createState() => _MinePageState();
}

class _MinePageState extends State<MinePage> {
  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
         slivers: <Widget>[
           SliverAppBar(
             pinned: true,
             stretch: true,
             expandedHeight: 200.0,
             flexibleSpace: FlexibleSpaceBar(
               title: Text('開(kāi)學(xué)季'),
               background: Image.network(
                 "https://goss.cfp.cn/creative/vcg/800/new/VCG211165042753.jpg",
                 fit: BoxFit.cover,
               ),
             ),
           ),
           SliverPadding(padding: EdgeInsets.only(top: 10),),
           SliverGrid(
             //調(diào)整間距
             gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
               crossAxisSpacing: 10,
               maxCrossAxisExtent: 200,
               mainAxisSpacing: 10,
               childAspectRatio: 4.0
             ),
             //加載內(nèi)容
             delegate: SliverChildBuilderDelegate(
                 (context,index) {
                   return Container( //設(shè)置每個(gè)item的內(nèi)容
                     alignment: Alignment.center,
                     color: Colors.orangeAccent,
                     child: Text("$index"),
                   );
                 },
               childCount: 20, //設(shè)置個(gè)數(shù)
             ),
           ),
           SliverPadding(padding: EdgeInsets.only(top: 10),),
           SliverFixedExtentList(
             itemExtent: 50,
             //加載內(nèi)容
             delegate: SliverChildBuilderDelegate(
                 (context, index) {
                   return Container(
                     alignment: Alignment.center,
                     color: Colors.deepPurpleAccent,
                     child: Text('$index'),
                   );
                 },
               //設(shè)置顯示個(gè)數(shù)
               childCount: 20,
             ),
           )
         ],
    );
  }
}
2020-04-13 18.14.54.gif
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容