Flutter SliverAppBar全解析,你要的效果都在這了!

轉載請聲明出處!!!

先來簡單看下部分效果圖:
在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述

本文內容可能有點多,但是都很簡單,配上效果圖味道更佳~


什麼是SliverAppBar

SliverAppBar 類似於Android中的CollapsingToolbarLayout,可以輕鬆實現頁面頭部展開、合併的效果。
與AppBar大部分的屬性重合,相當於AppBar的加強版。


先從最基本的效果開始,一步一步做到全效果。


常用屬性

  const SliverAppBar({
    Key key,
    this.leading,//左側的圖標或文字,多爲返回箭頭
    this.automaticallyImplyLeading = true,//沒有leading爲true的時候,默認返回箭頭,沒有leading且爲false,則顯示title
    this.title,//標題
    this.actions,//標題右側的操作
    this.flexibleSpace,//可以理解爲SliverAppBar的背景內容區
    this.bottom,//SliverAppBar的底部區
    this.elevation,//陰影
    this.forceElevated = false,//是否顯示陰影
    this.backgroundColor,//背景顏色
    this.brightness,//狀態欄主題,默認Brightness.dark,可選參數light
    this.iconTheme,//SliverAppBar圖標主題
    this.actionsIconTheme,//action圖標主題
    this.textTheme,//文字主題
    this.primary = true,//是否顯示在狀態欄的下面,false就會佔領狀態欄的高度
    this.centerTitle,//標題是否居中顯示
    this.titleSpacing = NavigationToolbar.kMiddleSpacing,//標題橫向間距
    this.expandedHeight,//合併的高度,默認是狀態欄的高度加AppBar的高度
    this.floating = false,//滑動時是否懸浮
    this.pinned = false,//標題欄是否固定
    this.snap = false,//配合floating使用
  })

基本效果

在這裏插入圖片描述

    return Scaffold(
      body: new CustomScrollView(
        slivers: <Widget>[
          new SliverAppBar(
            title: Text("標題"),
            expandedHeight: 230.0,
            floating: false,
            pinned: true,
            snap: false,
          ),
          new SliverFixedExtentList(
            itemExtent: 50.0,
            delegate: new SliverChildBuilderDelegate(
              (context, index) => new ListTile(
                    title: new Text("Item $index"),
                  ),
              childCount: 30,
            ),
          ),
        ],
      ),
    );

這是最最最基本的效果了,但是也簡陋的不行,下面開始一步一步改造。


添加leading

            leading: new IconButton(
              icon: Icon(Icons.arrow_back),
              onPressed: () {},
            ),

在這裏插入圖片描述


添加actions

            actions: <Widget>[
              new IconButton(
                icon: Icon(Icons.add),
                onPressed: () {
                  print("添加");
                },
              ),
              new IconButton(
                icon: Icon(Icons.more_horiz),
                onPressed: () {
                  print("更多");
                },
              ),
            ],

在這裏插入圖片描述


滑動標題上移效果

去掉title,添加flexibleSpace

            flexibleSpace: new FlexibleSpaceBar(
              title: new Text("標題標題標題"),
              centerTitle: true,
              collapseMode: CollapseMode.pin,
            ),

在這裏插入圖片描述


背景圖片沉浸式

項目根目錄下新建images文件夾,存放圖片,隨便選一張即可。
要加載本地圖片,還需要在pubspec.yaml 文件中配置一下

  assets:
    - images/a.jpg

修改flexibleSpace

            flexibleSpace: new FlexibleSpaceBar(
              background: Image.asset("images/a.jpg", fit: BoxFit.fill),
            ),

在這裏插入圖片描述


各種滑動效果演示

  • floating: false, pinned: true, snap: false:
    在這裏插入圖片描述

  • floating: true, pinned: true, snap: true:
    在這裏插入圖片描述

  • floating: false, pinned: false, snap: false:
    在這裏插入圖片描述

  • floating: true, pinned: false, snap: false:
    在這裏插入圖片描述

總結:仔細觀察,區別主要在於:

  • 標題欄是否跟着一起滑動
  • 上滑的時候,SliverAppBar是直接滑上去還是先合併然後再滑上去。
  • 下拉的時候,SliverAppBar是直接拉下來還是先拉下來再展開。

添加TabBar

在SliverAppBar的bottom屬性中添加TabBar,直接改造源碼中的例子

var _tabs = <String>[];
    _tabs = <String>[
      "Tab 1",
      "Tab 2",
      "Tab 3",
    ];
      /// 加TabBar
      DefaultTabController(
        length: _tabs.length, // This is the number of tabs.
        child: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            // These are the slivers that show up in the "outer" scroll view.
            return <Widget>[
              SliverOverlapAbsorber(
                handle:
                    NestedScrollView.sliverOverlapAbsorberHandleFor(context),
                child: SliverAppBar(
                  leading: new IconButton(
                    icon: Icon(Icons.arrow_back),
                    onPressed: () {},
                  ),
                  title: const Text('標題'),
                  centerTitle: false,
                  pinned: true,
                  floating: false,
                  snap: false,
                  primary: true,
                  expandedHeight: 230.0,

                  elevation: 10,
                  //是否顯示陰影,直接取值innerBoxIsScrolled,展開不顯示陰影,合併後會顯示
                  forceElevated: innerBoxIsScrolled,

                  actions: <Widget>[
                    new IconButton(
                      icon: Icon(Icons.more_horiz),
                      onPressed: () {
                        print("更多");
                      },
                    ),
                  ],

                  flexibleSpace: new FlexibleSpaceBar(
                    background: Image.asset("images/a.jpg", fit: BoxFit.fill),
                  ),

                  bottom: TabBar(
                    tabs: _tabs.map((String name) => Tab(text: name)).toList(),
                  ),
                ),
              ),
            ];
          },
          body: TabBarView(
            // These are the contents of the tab views, below the tabs.
            children: _tabs.map((String name) {
              //SafeArea 適配劉海屏的一個widget
              return SafeArea(
                top: false,
                bottom: false,
                child: Builder(
                  builder: (BuildContext context) {
                    return CustomScrollView(
                      key: PageStorageKey<String>(name),
                      slivers: <Widget>[
                        SliverOverlapInjector(
                          handle:
                              NestedScrollView.sliverOverlapAbsorberHandleFor(
                                  context),
                        ),
                        SliverPadding(
                          padding: const EdgeInsets.all(10.0),
                          sliver: SliverFixedExtentList(
                            itemExtent: 50.0, //item高度或寬度,取決於滑動方向
                            delegate: SliverChildBuilderDelegate(
                              (BuildContext context, int index) {
                                return ListTile(
                                  title: Text('Item $index'),
                                );
                              },
                              childCount: 30,
                            ),
                          ),
                        ),
                      ],
                    );
                  },
                ),
              );
            }).toList(),
          ),
        ),
      ),

在這裏插入圖片描述

關於TabBar的使用可以看這篇:https://blog.csdn.net/yechaoa/article/details/90482127


ok,以上的效果基本滿足日常開發需求了,也可以自己改改屬性測試效果。


demo github : https://github.com/yechaoa/flutter_sliverappbar


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章