携手创造,一起生长!这是我参与「日新方案 8 月更文应战」的第5天,点击检查活动详情

前语

继完成自定义TabBar主题色装备完成TabBar主题色定制后,对全体页面做定制化主题色装备更加具有沉浸式作用。因而为了更好体现出主题色装备特色,本次对页面全体做定制化主题色完成做一次介绍。

【Flutter】实现页面沉浸式主题色配置

完成进程

布景沉浸式装备

依据需求描述需求对顶部透出布景做主题切换作用。当频道页面做左右滑动操作时,页面布景也会随之发生改变。原有的框架结构如下所示:

/// 伪代码方式
NestedScrollView(
  headerSliverBuilder:(
    SliverAppBar(
      flexibleSpace:MagicFlexibleSpaceBar()
      bottom: TabBar()
    )
  )
  body:TabBarView(
    CustomScrollView(
      CupertinoSliverRefreshControl()
      SliverFixedExtentList()
    )
    ///同上CustomScrollView
    ....
  )
)

假如需求添加布景色覆盖住全局就必须将NestedScrollView嵌套在布局内部。可采用Stack方式讲主题布景作为底层布局在全体页面下方呈现出来,此外只需求为BackgroundThemes组件提供页面滑动监听即可完成主题布景切换的作用。

/// 伪代码方式
Stack(
  BackgroundThemes[]//主题切换组件
  NestedScrollView(
  headerSliverBuilder:(
    SliverAppBar(
      flexibleSpace:MagicFlexibleSpaceBar()
      bottom: TabBar()
    )
  )
  body:TabBarView(
    CustomScrollView(
      CupertinoSliverRefreshControl()
      SliverFixedExtentList()
    )
    ///同上CustomScrollView
    ....
  )
)
)

经过获取到Tab控制器偏移量得知当时页面下标,经过装备主题布景数组picUrls得到当时布景图,内部使用Stack来完成当时和下一个页面布景切换功能(切换进程带有透明度改变使得切换进程更为天然),切换详细完成如下:

Positioned(
          top: 0.0,
          left: 0.0,
          right: 0.0,
          /// 监听
          child:  AnimatedBuilder(
              animation: tabController1.animation,
              builder: (context, child) {
                // 与之前完成TabBar指示器的办法一样
                double page = 0;
                int realPage = 0;
                page = tabController1.index + tabController1.offset ?? 0;
                realPage =
                    tabController1.index + tabController1.offset?.floor() ?? 0;
                double opacity = 1 - (page - realPage).abs();
                int nextIndex =
                realPage + 1 < colors.length ? realPage + 1 : realPage;
                String thisPic = picUrls[realPage];
                String nextPic = picUrls[
                realPage + 1 < picUrls.length ? realPage + 1 : realPage];
                List<Widget> childs = List();
                //当时页面的布景图片
                if (thisPic != null && thisPic != '') {
                  childs.add(
                    Opacity(
                      opacity: opacity,
                      child: Image.asset(
                        thisPic,
                        fit: BoxFit.fitWidth,
                        alignment: Alignment.topCenter,
                      ),
                    ),
                  );
                }
                //下一个页面的布景图片
                if (nextPic != null && nextPic != '') {
                  childs.add(Opacity(
                    opacity: 1 - opacity,
                    child: Image.asset(
                      picUrls[realPage + 1 < picUrls.length
                          ? realPage + 1
                          : realPage],
                      fit: BoxFit.fitWidth,
                      alignment: Alignment.topCenter,
                    ),
                  ));
                }
                return Stack(
                  children: childs,
                );
              }),
        ),

布景主题完成需求将SliverAppBar以及内部FlexibleSpaceBar的布景色设置为Colors.transparent来透出布景。

【Flutter】实现页面沉浸式主题色配置

上滑顶部栏躲藏以及布景透出

完成布景色主题之后继续完成顶部上滑时底部列表不隐瞒布景。

【Flutter】实现页面沉浸式主题色配置

为处理默许完成是这样的,当做上滑操作时顶部栏可以正常躲藏但上滑列表会将布景色图片隐瞒。这是由于NestedScrollView以及其内部组件完成有关,上滑联动headerSliverBuilder组件是悬浮之上和body会堆叠的。若希望完成不堆叠的作用就需求只对body做滑动操作,因而需求改动点是将NestedScrollView设置为不可滑动的组件,一起赋值ScrollControllerbodyCustomScrollView设置本身ScrollController并且嵌套NotificationListener来监听滑动,当在body在指定范围内滑动联动带上NestedScrollView滑动。实际上该操作便是将NestedScrollView内部的outScroller释放掉,让开发自行控制body滑动操作以此来防止上下组件堆叠。

NestedScrollView(
controller: fatherController,
physics: NeverScrollableScrollPhysics(),
body:TabBarView(
  children:[
    NotificationListener(
      onNotification:(position) {
        // 获取到position 和 fatherController 做比较
        // 依据滑动情况 对fatherController做移动操作
      }
      child: CustomScrollView(
        controller: scrollController,
        physics: NestedClampingScrollPhysics(),
      )
    )
  ]
)
)

【Flutter】实现页面沉浸式主题色配置

全体功能展现

详细完成代码看这儿