Flutter 52: 图解可折叠状态栏

简介: 0 基础学习 Flutter,第五十二步:学习一下可折叠状态栏!

      顶部状态栏在日常中是必不可少的,今天小菜尝试一下可折叠状态栏的使用;

      小菜以前在学习滑动冲突时曾用过 Sliver 系列的 Widget,小菜这次尝试用 SliverAppBar 来处理;

SliverAppBar

源码分析

const SliverAppBar({
    Key key,
    this.leading,
    this.automaticallyImplyLeading = true,
    this.title,
    this.actions,
    this.flexibleSpace,
    this.bottom,
    this.elevation,
    this.forceElevated = false,
    this.backgroundColor,
    this.brightness,
    this.iconTheme,
    this.textTheme,
    this.primary = true,
    this.centerTitle,
    this.titleSpacing = NavigationToolbar.kMiddleSpacing,
    this.expandedHeight,
    this.floating = false,
    this.pinned = false,
    this.snap = false,
})

      leading:顶部左侧 Widget 常见的是返回按钮;

      automaticallyImplyLeading:配合 leading 使用,若未设置 leading 且设为 false 时,标题位置整体向左移动,占据 leading 原本位置;

      title:顶部标题 Widget 常见的是文字标题等;

      centerTitletrue 为标题 Widget 居中,false 默认居左;

      actions:顶部右侧菜单组,可设置多个菜单按钮等;

actions: <Widget>[
    Icon(Icons.add), Icon(Icons.info),
    Padding( child: Icon(Icons.delete), padding: EdgeInsets.symmetric(horizontal: 10.0))],


      elevation:滑动过程中标题栏与列表交界处;

      forceElevated:与 elevation 共同使用,false 时不展示,true 时根据 elevation 设置效果展示;

      backgroundColor:背景色;

      brightness:主题亮度,主要是 lightdark 两种;

      iconTheme:图标主题,包括 leading / actions 等主题;

      textTheme:文字主题,包括标题等,通常与上述两种共同使用;

brightness: Brightness.dark,
iconTheme: IconThemeData(color: Colors.black26),
textTheme: TextTheme(title: TextStyle(color: Colors.black26)),

      primarytrue 占据系统状态栏位置,false 相反;

      bottom:添加状态栏底部小部件,需要是 PreferredSizeWidget 类型 Widget

bottom: TabBar(tabs: [
   Tab(icon: Icon(Icons.border_left), text: '左侧'),
   Tab(icon: Icon(Icons.border_clear), text: '居中'),
   Tab(icon: Icon(Icons.border_right), text: '右侧')
], controller: TabController(length: 3, vsync: this)),

      expandedHeight:状态栏展开高度;

      flexibleSpace:状态栏展开 Widget

flexibleSpace: FlexibleSpaceBar(
    title: Text('标题'),
    background: Image.asset('images/icon_header.jpg', fit: BoxFit.cover),
    centerTitle: true),

      pinnedtrue滑动后固定折叠状态栏,false 直接滑上去;

      floating:滑动过程中效果,通常与 snap pinned 共同使用,且 floatingture 时,snap 也一般为 true;官方推荐的样例视频很好的诠释出滑动过程中列表的滑动与顶部状态栏滑动变化;

  1. floating: false, pinned: false, snap: false
  2. floating: true, pinned: false, snap: false
  3. floating: true, pinned: false, snap: true
  4. floating: true, pinned: true, snap: false
  5. floating: true, pinned: true, snap: true
  6. floating: false, pinned: true, snap: false
class _SliverListPage extends State<SliverListPage> with TickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: CustomScrollView(slivers: <Widget>[
      SliverAppBar(
        title: Text('Sliver Title Sliver Title Sliver Title'),
        leading: Icon(Icons.reply),
        automaticallyImplyLeading: true,
        actions: <Widget>[
          Icon(Icons.add), Icon(Icons.info),
          Padding( child: Icon(Icons.delete), padding: EdgeInsets.symmetric(horizontal: 10.0)),
        ],
        flexibleSpace: FlexibleSpaceBar(
            title: Text('标题'),
            background: Image.asset('images/icon_header.jpg', fit: BoxFit.cover),
            centerTitle: true),
        expandedHeight: 200,
        backgroundColor: Colors.pinkAccent,
        elevation: 16.0,
        centerTitle: false,
        primary: true,
        floating: true,
        pinned: false,
        snap: true,
      ),
      SliverList(
          delegate: SliverChildBuilderDelegate(
              (_, index) => ListTile(title: Text('当前 item 为: ${(index + 1)}'))))
    ]));
  }
}

SliverPersistentHeader

      随着需求的不同,对折叠栏的样式要求也不相同,接下来是小菜研究的重点,自定义折叠栏样式;

源码分析

const SliverPersistentHeader({
    Key key,
    @required this.delegate,
    this.pinned = false,
    this.floating = false,
})

      小菜主要实现 SliverPersistentHeaderDelegate;需要实现四个方法:

      build 是页面布局效果,其中 shrikOffset 为滑动距离,直到设置的折叠展开高度;

      maxExtent 折叠状态栏展开的最大高度;

      minExtent 折叠状态栏收起的最小高度(pinned=true);当 maxExtent=minExtent 时,状态栏不折叠;

      shouldRebuild 判断是否与旧的不同,是否需要重绘;

class MySliverAppBar extends SliverPersistentHeaderDelegate {
  final double expandedHeight;
  MySliverAppBar({@required this.expandedHeight});

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Stack(fit: StackFit.expand, children: [
      Image.asset('images/icon_header.jpg', fit: BoxFit.cover),
      Center(
          child: Opacity(
              opacity: 1 - shrinkOffset / expandedHeight,
              child: Offstage(
                  child: _listHeaderWid(),
                  offstage: shrinkOffset <= 20.0 ? false : true))),
      Positioned(
          top: 20.0,
          child: Container(
              height: 45.0,
              width: MediaQuery.of(context).size.width,
              child: Opacity(
                  opacity: 1,
                  child: Padding(
                      padding: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
                      child: Row(children: <Widget>[
                        Expanded( child: Text('测试应用', style: TextStyle( color: Color(0xFF333333), fontSize: 18.0))),
                        GestureDetector(
                            onTap: () {},
                            child: Padding(
                                padding: EdgeInsets.fromLTRB(0.0, 0.0, 20.0, 0.0),
                                child: Image.asset('images/icon_shelf_search.png', width: 22.0, height: 22.0))),
                        GestureDetector(
                            onTap: () async {},
                            child: Image.asset('images/icon_shelf_more.png', width: 22.0, height: 22.0))
                      ])))))
    ]);
  }

  Widget _listHeaderWid() {
    return Container(
        height: 84.0,
        margin: EdgeInsets.only(top: 75.0),
        child: Padding(
            padding: EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
            child: Row(children: <Widget>[
              Expanded(
                  flex: 1,
                  child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      mainAxisSize: MainAxisSize.max,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text('精彩世界', style: TextStyle(color: Colors.white, fontSize: 18.0)),
                        Padding(
                            padding: EdgeInsets.fromLTRB(0.0, 4.0, 0.0, 4.0),
                            child: Text('点击兑换奖励', style: TextStyle( color: Colors.white, fontSize: 12.0)))
                      ])),
              Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  mainAxisSize: MainAxisSize.max,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Container(
                        height: 32.0, width: 84.0,
                        decoration: BoxDecoration(
                            shape: BoxShape.rectangle,
                            gradient: LinearGradient(colors: <Color>[
                              Colors.orange, Colors.deepOrange ]),
                            borderRadius: BorderRadius.circular(50.0)),
                        child: Center( child: Text('签到有奖', style: TextStyle( color: Colors.white, fontSize: 14.0))))
                  ])
            ])));
  }

  @override
  double get maxExtent => expandedHeight;

  @override
  double get minExtent => 75.0;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
}


      小菜对折叠状态栏的认知还不够深入,如有问题请多多指教!

来源:阿策小和尚

目录
相关文章
|
10月前
|
Android开发 iOS开发
Flutter应用开发,系统样式改不了?SystemChrome 状态栏、导航栏、屏幕方向……想改就改
Flutter应用开发,系统样式改不了?SystemChrome 状态栏、导航栏、屏幕方向……想改就改
|
Dart 开发者
【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )(三)
【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )(三)
195 0
【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )(三)
【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )(二)
【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )(二)
224 0
【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )(一)
【Flutter】监听滚动动作 控制组件 透明度渐变 ( 移除顶部状态栏空白 | 帧布局组件 | 透明度组件 | 监听滚动组件 )(一)
136 0
|
容器 开发工具 git
Flutter 31: 图解自定义底部状态栏 ACEBottomNavigationBar (二)
0 基础学习 Flutter,第三十一步:补充自定义底部状态栏样式并发布第一版 Pub 插件~
2387 0
|
容器
Flutter 30: 图解自定义底部状态栏 ACEBottomNavigationBar (一)
0 基础学习 Flutter,第三十步:自定义底部状态栏~
4698 0
|
Android开发 索引 容器
Flutter 11: 图解底部状态栏小尝试
      小菜今天来整理一下在学习测试 Flutter 时需用到的底部导航栏 BottomNavigationBar,使用方式很简单,小菜感觉效果比原生的 Android 要好一些。
2831 0
|
3月前
|
监控 Dart 安全
创建一个Dart应用,监控局域网上网记录的软件:Flutter框架的应用
在当今数字时代,网络安全变得愈发重要。为了监控局域网上的上网记录,我们可以借助Flutter框架创建一个强大的Dart应用。在这篇文章中,我们将深入讨论如何使用Flutter框架开发这样一个监控局域网上网记录的软件,并提供一些实用的代码示例。
273 1
|
6月前
|
Dart Android开发 UED
带你读《深入浅出Dart》二十七、Flutter路由管理
带你读《深入浅出Dart》二十七、Flutter路由管理
|
2月前
|
Dart JavaScript
Flutter - Dart 基础(数据类型)
【2月更文挑战第3天】
61 1