5

前言

在业务开发中我们经常会有滚动吸顶的效果,目前Flutter也有很多种实现方式,这里介绍一下本人在开发中使用到的基于NestedScrollView实现的滚动吸顶组件;以及中间涉及的各种定位的布局操作;

效果

3AA6C32F47694FA7CE40FEC465D20071

NestedScrollView

首先了解一下NestedScrollView滚动组件;

NestedScrollView:支持嵌套滑动的ScrollView;

属性

属性说明默认值
controller滚动监听
scrollDirection滚动方向Axis.vertical 默认垂直方向
reverse是都倒叙false 默认值
physics控制用户滚动视图的交互AlwaysScrollableScrollPhysics 总是可以滑动
NeverScrollableScrollPhysics 禁止滚动
BouncingScrollPhysics 内容超过一屏上拉有回弹效果
ClampingScrollPhysics 包裹内容不会有回弹
headerSliverBuilder折叠头部
body滚动组件实体

NestedScrollView折叠部分使用SliverAppBar来实现

SliverAppBar

代码示例

NestedScrollView(
    controller: _scrollController,
    headerSliverBuilder: _headerSliverBuilder,
    body: buildSliverBody(context)
)
///页面滚动头部处理
List<Widget> _headerSliverBuilder(BuildContext context, bool innerBoxIsScrolled) {
  return <Widget> [
    buildSliverAppBar(context)
  ];
}
///导航部分渲染
Widget buildSliverAppBar(BuildContext context) {
  return SliverAppBar(
    //当此值为true时 SliverAppBar 会固定在页面顶部
    //当此值为fase时 SliverAppBar 会随着滑动向上滑动
    pinned: true,
    //滚动是是否拉伸图片
    stretch: true,
    //展开区域的高度
    expandedHeight: 500,
    //当snap配置为true时,向下滑动页面,SliverAppBar(以及其中配置的flexibleSpace内容)会立即显示出来,
    //反之当snap配置为false时,向下滑动时,只有当ListView的数据滑动到顶部时,SliverAppBar才会下拉显示出来。
    snap: false,
    //阴影
    elevation: 0,
    //背景颜色
    backgroundColor: headerWhite? Colors.white : Color(0xFFF4F5F7),
    //App bar 的亮度,有白色和黑色两种主题,默认值为 ThemeData.primaryColorBrightness
    brightness: Brightness.light,
    //在标题左侧显示的一个控件,在首页通常显示应用的 logo;在其他界面通常显示为返回按钮
    leading: IconButton(
        icon: Image.network(backIcon, height: 22, width: 22,),
        onPressed: (){
          //TODO: 返回事件处理
        }
    ),
        //一个显示在 AppBar 下方的控件,高度和 AppBar 高度一样, // 可以实现一些特殊的效果,该属性通常在 SliverAppBar 中使用
    flexibleSpace: FlexibleSpaceBar(
      title: headerWhite ? Text('长津湖', style: TextStyle(
          color: Color(0xFF333333),
          fontWeight: FontWeight.w700,
          fontSize: 17,
          fontFamily: 'PingFangSC-Semibold'
      ),) : Text(''),
      //标题居中
      centerTitle: true,
      background: buildAppBarBackground(context),
    ),
  );
}

属性

const SliverAppBar({
    Key key,
    this.leading,         //在标题左侧显示的一个控件,在首页通常显示应用的 logo;在其他界面通常显示为返回按钮
    this.automaticallyImplyLeading = true,//? 控制是否应该尝试暗示前导小部件为null
    this.title,               //当前界面的标题文字
    this.actions,          //一个 Widget 列表,代表 Toolbar 中所显示的菜单,对于常用的菜单,通常使用 IconButton 来表示;对于不常用的菜单通常使用 PopupMenuButton 来显示为三个点,点击后弹出二级菜单
    this.flexibleSpace,        //一个显示在 AppBar 下方的控件,高度和 AppBar 高度一样, // 可以实现一些特殊的效果,该属性通常在 SliverAppBar 中使用
    this.bottom,         //一个 AppBarBottomWidget 对象,通常是 TabBar。用来在 Toolbar 标题下面显示一个 Tab 导航栏
    this.elevation,            //阴影
    this.forceElevated = false, 
    this.backgroundColor,       //APP bar 的颜色,默认值为 ThemeData.primaryColor。改值通常和下面的三个属性一起使用
    this.brightness,   //App bar 的亮度,有白色和黑色两种主题,默认值为 ThemeData.primaryColorBrightness
    this.iconTheme,  //App bar 上图标的颜色、透明度、和尺寸信息。默认值为 ThemeData().primaryIconTheme
    this.textTheme,    //App bar 上的文字主题。默认值为 ThemeData().primaryTextTheme
    this.primary = true,  //此应用栏是否显示在屏幕顶部
    this.centerTitle,     //标题是否居中显示,默认值根据不同的操作系统,显示方式不一样,true居中 false居左
    this.titleSpacing = NavigationToolbar.kMiddleSpacing,//横轴上标题内容 周围的间距
    this.expandedHeight,     //展开高度
    this.floating = false,       //是否随着滑动隐藏标题
    this.pinned = false,  //是否固定在顶部
    this.snap = false,   //与floating结合使用
  })

flexibleSpace

flexibleSpace: FlexibleSpaceBar(
  //是否展示标题
  title: headerWhite ? Text('长津湖', style: TextStyle(
      color: Color(0xFF333333),
      fontWeight: FontWeight.w700,
      fontSize: 17,
      fontFamily: 'PingFangSC-Semibold'
  ),) : Text(''),
  //标题居中
  centerTitle: true,
  //折叠部分背景图片
  background: Container(
      height: 400,
      width: ScreenUtil().screenWidth,
      decoration: BoxDecoration(
          image: DecorationImage(
              image: NetworkImage('https://p0.meituan.net/movie/0e81560dc9910a6a658a82ec7a054ceb5075992.jpg@464w_644h_1e_1c'),
              fit: BoxFit.fill
          )
      ),
    ),
)

展示标题如下:

image-20211115145812098

不展示标题滚动到某个位置时在展示 如下:

image-20211115145916035

完整代码

完整代码


兰俊秋雨
5.1k 声望3.5k 粉丝

基于大前端端技术的一些探索反思总结及讨论