Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

The top status bar is essential in everyday life, so today’s tip is to try the use of a collapsible status bar;

Koshi has used the Sliver series of widgets before in learning about sliding conflicts. This time, Koshi tries to use the SliverAppBar.

SliverAppBar

Source code analysis

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,
})
Copy the code

Leading: The back button is common in the top left Widget;

AutomaticallyImplyLeading: cooperate with leading to use, if not set leading and set to false, the caption location moved to the left, leading the original position;

      title: Top titleWidgetCommon is the text title and so on;

CenterTitle: true centers the title Widget, false defaults to the left;

Actions: top right menu group, can set multiple menu buttons, etc.

actions: <Widget>[ Icon(Icons.add), Icon(Icons.info), Padding( child: Icon(Icons.delete), padding: EdgeInsets. Symmetric (horizontal: 10.0)),Copy the code

Elevation: the interface between the title bar and the list during sliding;

ForceElevated: used with elevation, false does not display, true according to elevation setting effect display;

      backgroundColor: background color;

Brightness: Brightness of the theme, mainly light and dark;

IconTheme: iconTheme, including leading/actions, etc.

TextTheme: a textTheme, including a title, and so on, usually used together with both of the above;

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

Primary: true occupies the status bar of the system, false does the opposite;

Bottom: Add the Widget at the bottom of the status bar. The Widget should be of type PreferredSizeWidget.

Bottom: TabBar(tabs: [Tab(icon: icon (Icons. Border_left), text: 'left '), Tab(icon: icon (Icons. Border_clear), text: tabs: [Tab(icon: icon (Icons. 'center '), Tab(icon: icon (Icons. Border_right), text:' right ')], Controller: TabController(length: 3, vsync: this),Copy the code

ExpandedHeight: Expansion height of the status bar;

FlexibleSpace: Status bar to expand widgets;

FlexibleSpace: FlexibleSpaceBar (title: Text (' title '), and background: Image. The asset (' images/icon_header. JPG, fit: BoxFit.cover), centerTitle: true),Copy the code

Pinned: true slide and fix the status bar, false slide directly up;

Floating: effect during a slide, often used with snap pinned, and if floating is true, snap is also generally pinned; The sample video recommended by the official is a good explanation of the list sliding and the top status bar sliding changes in the sliding process;

  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(' title '), BACKGROUND: FlexibleSpaceBar Image.asset('images/icon_header.jpg', fit: BoxFit.cover), centerTitle: true), expandedHeight: 200, backgroundColor: PinkAccent, elevation: 16.0, centerTitle: false, primary: true, floating: true, pinned: false, snap: True,), SliverList (delegate: SliverChildBuilderDelegate ((_, index) = > ListTile (title: Text (' current item for: ${(index + 1)}')))) ])); }}Copy the code

SliverPersistentHeader

With the different needs, the style requirements of the folding bar are not the same, next is the focus of the small dish research, custom folding bar style;

Source code analysis

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

Side dish SliverPersistentHeaderDelegate main implementation; Four methods need to be implemented:

Build is the page layout effect, where shrikOffset is the sliding distance until the set height of folding expansion;

MaxExtent Indicates the maximum expansion height of the status bar.

MinExtent Minimum height of the status bar fold (pinned=true); When maxExtent is minExtent, the status bar does not collapse.

ShouldRebuild determines if it is different from the old one and needs to be redrawn;

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: Toy (top: 20.0, child: Container(height: 45.0, width: MediaQuery. Of (context).size. Opacity(Opacity: 1), child: Padding(Opacity: edgeinset.fromltrb), child: Row(children: <Widget>[Expanded(child: Text(' test application ', style: TextStyle(color: color (0xFF333333), fontSize: 5.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. The 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, and the children: "Widget > [Text (' wonderful world, style: TextStyle (color: Colors. White, fontSize: Background-color: RGB (255,255,255); background-color: RGB (255,255); background-color: RGB (255,255); background-color: RGB (255,255); background-color: RGB (255,255); background-color: RGB (255,255); background-color: RGB (255,255); Colors. White, fontSize: 12.0))))), Column (mainAxisAlignment: mainAxisAlignment center, mainAxisSize: MainAxisSize. Max, crossAxisAlignment: crossAxisAlignment. Start, children: < widgets > [Container (height: 32.0, width: 84.0, rectangle: BoxDecoration(shape: BoxShape. Rectangle: gradient: LinearGradient(colors: <Color>[color.orange, color.deeporange]), borderRadius: borderRadius. Circular (50.0)), child: Center(child: Color: color.white, fontSize: 14.0))))])); } @override double get maxExtent => expandedHeight; @override double get minExtent => 75.0; @override bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true; }Copy the code


Xiao CAI’s cognition of folding status bar is not deep enough, if you have any questions, please give me more advice!

Source: Little Monk A Ce