5

Preface

In business development, we often have the effect of scrolling ceiling. At present, Flutter also has many ways to implement it. Here, I will introduce the scroll ceiling component based on NestedScrollView that I used in development; and the layout of various positioning involved in the middle. operate;

Effect

3AA6C32F47694FA7CE40FEC465D20071

NestedScrollView

First understand the NestedScrollView scrolling component;

NestedScrollView: ScrollView that supports nested sliding;

Attributes

AttributesillustrateDefaults
controllerScroll monitorwithout
scrollDirectionScroll directionAxis.vertical default vertical direction
reverseAre all flashbacksfalse default
physicsControl the user's scroll view interactionAlwaysScrollableScrollPhysics can always slide
NeverScrollableScrollPhysics prohibit rolling
BouncingScrollPhysics content has pulled rebound effect on more than one screen
ClampingScrollPhysics package contents will not rebound
headerSliverBuilderFold the headwithout
bodyScroll component entitywithout

The folding part of NestedScrollView is implemented using SliverAppBar

SliverAppBar

Code example

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),
    ),
  );
}

Attributes

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
          )
      ),
    ),
)

The display title is as follows:

image-20211115145812098

When scrolling to a certain position, the title is displayed as follows:

image-20211115145916035

Complete code

complete code


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

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