根据页面需求想思路之CustomScrollView

1,738 阅读2分钟

关于Flutter中CustomScrollView+SliverAppBar+SliverList

需求背景:

WX20210818-083249@2x.png

WX20210818-083256@2x.png

图1为正常状态下,滑动状态下为图二。 对于iOS或者android项目开发老哥来说这种实现已经是很熟练了。但是用flutter来说。一开始还是一脸懵逼。后来查了查资料。总结下,当前的需求可通过 CustomScrollView+SliverAppBar+SliverList实现。

CustomScrollView

首先看下CustomScrollView官方提供的代码:

    Key? key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController? controller,
    bool? primary,
    ScrollPhysics? physics,
    ScrollBehavior? scrollBehavior,
    bool shrinkWrap = false,
    Key? center,
    double anchor = 0.0,
    double? cacheExtent,
    this.slivers = const <Widget>[],
    int? semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
    String? restorationId,
    Clip clipBehavior = Clip.hardEdge,

参数中,设置的一些参数,从文字的意思或者猜测,基本上都能了解个差不多。 这里面有个 slivers一个Widget的数组。应该就是CustomScrollView的字试图部分

slivers

让我们在看下## slivers下面可以放哪些Widget呢?

1、SliverAppBar

    this.leading,
    this.automaticallyImplyLeading = true,
    this.title,
    this.actions,
    this.flexibleSpace,
    this.bottom,
    this.elevation,
    this.shadowColor,
    this.forceElevated = false,
    this.backgroundColor,
    this.foregroundColor,
    this.textTheme,
    this.primary = true,
    this.centerTitle,
    this.excludeHeaderSemantics = false,
    this.titleSpacing,
    this.collapsedHeight,
    this.expandedHeight,
    this.floating = false,
    this.pinned = false,
    this.snap = false,
    this.stretch = false,
    this.stretchTriggerOffset = 100.0,
    this.onStretchTrigger,
    this.shape,
    this.toolbarHeight = kToolbarHeight,
    this.leadingWidth,
    this.backwardsCompatibility,
    this.toolbarTextStyle,
    this.titleTextStyle,
    this.systemOverlayStyle,

对应的属性相应较多一点。按照当前需求:

Widget build(BuildContext context) {
    super.build(context);
    ScreenUtil.init(
      BoxConstraints(
          maxWidth: MediaQuery.of(context).size.width,
          maxHeight: MediaQuery.of(context).size.height),
      designSize: Size(375, 667),
    );
    return Scaffold(
      body: Stack(
        children: [
          CustomScrollView(
            controller: _scrollController,
            slivers: [
              SliverAppBar(
                title: Opacity(opacity: opacity, child: Text('快车道货运')),
                expandedHeight: 100.0,
                floating: true,
                pinned: true,
                actions: [
                  Opacity(
                      opacity: opacity,
                      child:
                          IconButton(onPressed: () {}, icon: Icon(Icons.add))),
                  Opacity(
                      opacity: opacity,
                      child: IconButton(
                          onPressed: () {}, icon: Icon(Icons.search)))
                ],
                backgroundColor: AppColors.nav,
                flexibleSpace: FlexibleSpaceBar(
                    centerTitle: false,
                    background: Container(
                      decoration: BoxDecoration(
                          gradient: LinearGradient(
                              colors: [AppColors.nav, AppColors.nav1])),
                      child: Row(
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: [
                          Expanded(
                              child: Container(
                            alignment: Alignment.center,
                            child: Text('自定义按钮'),
                          )),
                          Expanded(
                              child: Container(
                            alignment: Alignment.center,
                            child: Text('自定义按钮'),
                          ))
                        ],
                      ),
                    )),
              ),
              SliverList(
                  delegate:
                      SliverChildBuilderDelegate(_homeCell, childCount: 50)),
            ],
          ),
        ],
      ),
    );
  }

opacity为通过监_scrollController听滑动控制距离 是否显示按钮 当前需求 滑动之后显示的靠左显示的标题 右边两个icon。SliverAppBar提供的方法完全可以实现了。

如滑动收缩后的导航栏实现不了,因为导航栏滑动固定的,可以做一个自定义的widget固定在上面。通过滑动的幅度,显示还是隐藏

    floatingActionButton: 自定义widget,
    floatingActionButtonLocation: FloatingActionButtonLocation.centerTop,//位置

实现效果如下:

WX20210818-092529@2x.png

WX20210818-092539@2x.png

根据需求 SliverAppBarSliverList 中间有和头部试图。 要SliverList上面增加个header 根据文档里 发现了提供了 SliverPersistentHeader

SliverPersistentHeader(
    delegate: _homeSliverPersistentHeaderDelegate(),
    pinned: true,//是否固定
    floating: false,
  ),


//SliverPersistentHeaderDelegate 自定义 效果和SliverAppBar差不多
class _homeSliverPersistentHeaderDelegate
    extends SliverPersistentHeaderDelegate {
  final double _minExtent = 100;//滑动最小高度
  final double _maxExtent = 100;//最大高度
  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      child: 自定义试图,
    );
  }

实现效果图:

WX20210818-201117@2x.png

WX20210818-201128@2x.png

当前问题: 滑动之后的appBar的颜色渐变怎么实现?