Flutter 系列文章:Flutter SliverAppbar 控件介紹

flutter SliverAppbar 控件介紹

1、使用方法

  • 與CustomScrollView、NestedScrollView集成的材質設計應用欄。應用欄由工具欄和其餘小部件組成,例如 TabBar和FlexibleSpaceBar。應用欄一般會使用IconButton公開一個或多個常見操做,後者可選地後跟 PopupMenuButton以進行不太常見的操做bash

    image

  • 構造函數

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結合使用
  })
複製代碼

2、經常使用屬性

  1. 在標題前面顯示的一個控件,在首頁一般顯示應用的logo;在其餘界面一般顯示爲返回按鈕
leading: Icon(_selectedChoice.icon) ,
複製代碼
  1. 控制是否應該嘗試暗示前導小部件爲null
automaticallyImplyLeading:true ,
複製代碼
  1. 當前界面的標題文字
title: Text(_selectedChoice.title )
複製代碼
  1. 一個 Widget 列表,表明 Toolbar 中所顯示的菜單,對於經常使用的菜單,一般使用 IconButton 來表示;對於不經常使用的菜單一般使用 PopupMenuButton 來顯示爲三個點,點擊後彈出二級菜單
actions: <Widget>[
            new IconButton( // action button
              icon: new Icon(choices[0].icon),
              onPressed: () { _select(choices[0]); },
            ),
            new IconButton( // action button
              icon: new Icon(choices[1].icon),
              onPressed: () { _select(choices[1]); },
            ),
            new PopupMenuButton<Choice>( // overflow menu
              onSelected: _select,
              itemBuilder: (BuildContext context) {
                return choices.skip(2).map((Choice choice) {
                  return new PopupMenuItem<Choice>(
                    value: choice,
                    child: new Text(choice.title),
                  );
                }).toList();
              },
            )
          ],
複製代碼
  1. 一個顯示在 AppBar 下方的控件,高度和 AppBar 高度同樣,能夠實現一些特殊的效果,該屬性一般在 SliverAppBar 中使用
//        flexibleSpace: Container(
//          color: Colors.blue,
//          width: MediaQuery.of(context).size.width,
//          child: Text("aaaaaaaaaa"),
//          height: 10,
//        )
複製代碼
  1. 一個 AppBarBottomWidget 對象,一般是 TabBar。用來在 Toolbar 標題下面顯示一個 Tab 導航欄
bottom: new TabBar(
            isScrollable: true,
            tabs: choices.map((Choice choice) {
              return new Tab(
                text: choice.title,
                icon: new Icon(choice.icon),
              );
            }).toList(),
          ) 
複製代碼
  1. 材料設計中控件的 z 座標順序,默認值爲 4,對於可滾動的 SliverAppBar, 當 SliverAppBar 和內容同級的時候,該值爲 0, 當內容滾動 SliverAppBar 變爲 Toolbar 的時候,修改 elevation 的值
elevation: 1
複製代碼
  1. APP bar 的顏色,默認值爲 ThemeData.primaryColor。改值一般和下面的三個屬性一塊兒使用
backgroundColor: Colors.red,

複製代碼
  1. App bar 的亮度,有白色和黑色兩種主題,默認值爲 ThemeData.primaryColorBrightness
brightness:Brightness.light ,

複製代碼
  1. App bar 上圖標的顏色、透明度、和尺寸信息。默認值爲 ThemeData().primaryIconTheme
iconTheme: ThemeData().iconTheme,

複製代碼
  1. App bar 上的文字主題。默認值爲 ThemeData().primaryTextTheme
textTheme: ThemeData().accentTextTheme,

複製代碼
  1. 此應用欄是否顯示在屏幕頂部
primary: true,

複製代碼
  1. 標題是否居中顯示,默認值根據不一樣的操做系統,顯示方式不同,true居中 false居左
centerTitle: true,

複製代碼
  1. 橫軸上標題內容 周圍的間距
titleSpacing: NavigationToolbar.kMiddleSpacing,

複製代碼
  1. 頂部的工具欄部分的透明度 <=1.0
toolbarOpacity:1.0,

複製代碼
  1. bottom的工具欄部分的透明度 <=1.0
bottomOpacity: 0.5,

複製代碼
  1. appbar是否隨着滑動隱藏標題
floating: true,
複製代碼
  1. tab 是否固定在頂部
pinned: true,
複製代碼
  1. 與floating結合使用,若是snap和floating爲true,則浮動應用欄將「捕捉」到視圖中
snap: true,
複製代碼

3、一個完整的例子

一、與NestedScrollView 集成SliverAppBarapp

@override
  Widget build(BuildContext context) {
    return DefaultTabController(
        length: choices.length,
        child: Scaffold(
            body: NestedScrollView(
              headerSliverBuilder: _headerSliverBuilder,
              body : TabBarView(
                children: choices.map((Choice choice) {
                  return new Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: new ChoiceCard(choice: choice),
                  );
                }).toList(),
              ),
            )
        )
    );
  }
複製代碼

二、與CustomScrollView 集成SliverAppBarless

//例子2
  @override
  Widget build(BuildContext context) {
    return  Scaffold(
      body:CustomScrollView(
        slivers: <Widget>[
          const SliverAppBar(
            pinned: true,
            expandedHeight: 250.0,
            flexibleSpace: FlexibleSpaceBar(
              title: Text('Demo'),
            ),
          ),
          SliverGrid(
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
              maxCrossAxisExtent: 200.0,
              mainAxisSpacing: 10.0,
              crossAxisSpacing: 10.0,
              childAspectRatio: 4.0,
            ),
            delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                return Container(
                  alignment: Alignment.center,
                  color: Colors.teal[100 * (index % 9)],
                  child: Text('grid item $index'),
                );
              },
              childCount: 20,
            ),
          ),
          SliverFixedExtentList(
            itemExtent: 50.0,
            delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                return Container(
                  alignment: Alignment.center,
                  color: Colors.lightBlue[100 * (index % 9)],
                  child: Text('list item $index'),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
複製代碼
  1. 一個完整的例子
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text Demo',
      theme: ThemeData(
          primarySwatch: Colors.green
      ),
      home: MyHomePage(title: 'Text Demo'),
    );
  }
}


class MyHomePage extends StatefulWidget {

  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>{

  Choice _selectedChoice = choices[0]; // The app's "state". void _select(Choice choice) { setState(() { // Causes the app to rebuild with the new _selectedChoice. _selectedChoice = choice; }); } @override Widget build(BuildContext context) { return DefaultTabController( length: choices.length, child: Scaffold( body: NestedScrollView( headerSliverBuilder: _headerSliverBuilder, body : TabBarView( children: choices.map((Choice choice) { return new Padding( padding: const EdgeInsets.all(16.0), child: new ChoiceCard(choice: choice), ); }).toList(), ), ) ) ); } List<Widget> _headerSliverBuilder(BuildContext context, bool innerBoxIsScrolled){ return <Widget>[ SliverAppBar( //1.在標題左側顯示的一個控件,在首頁一般顯示應用的 logo;在其餘界面一般顯示爲返回按鈕 leading: Icon(_selectedChoice.icon) , //2. ? 控制是否應該嘗試暗示前導小部件爲null automaticallyImplyLeading:true , //3.當前界面的標題文字 title: Text(_selectedChoice.title ), //4.一個 Widget 列表,表明 Toolbar 中所顯示的菜單,對於經常使用的菜單,一般使用 IconButton 來表示; //對於不經常使用的菜單一般使用 PopupMenuButton 來顯示爲三個點,點擊後彈出二級菜單 actions: <Widget>[ new IconButton( // action button icon: new Icon(choices[0].icon), onPressed: () { _select(choices[0]); }, ), new IconButton( // action button icon: new Icon(choices[1].icon), onPressed: () { _select(choices[1]); }, ), new PopupMenuButton<Choice>( // overflow menu onSelected: _select, itemBuilder: (BuildContext context) { return choices.skip(2).map((Choice choice) { return new PopupMenuItem<Choice>( value: choice, child: new Text(choice.title), ); }).toList(); }, ) ], //5.一個顯示在 AppBar 下方的控件,高度和 AppBar 高度同樣, // 能夠實現一些特殊的效果,該屬性一般在 SliverAppBar 中使用 flexibleSpace: FlexibleSpaceBar( centerTitle: true, background: Image( image: NetworkImage("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1551944816841&di=329f747e3f4c2554f24c609fd6f77c49&imgtype=0&src=http%3A%2F%2Fimg.tupianzj.com%2Fuploads%2Fallimg%2F160610%2F9-160610114520.jpg"), fit: BoxFit.cover, ), ), //6.一個 AppBarBottomWidget 對象,一般是 TabBar。用來在 Toolbar 標題下面顯示一個 Tab 導航欄 bottom: new TabBar( isScrollable: true, tabs: choices.map((Choice choice) { return new Tab( text: choice.title, icon: new Icon(choice.icon), ); }).toList(), ) , //7.? 材料設計中控件的 z 座標順序,默認值爲 4,對於可滾動的 SliverAppBar, // 當 SliverAppBar 和內容同級的時候,該值爲 0, 當內容滾動 SliverAppBar 變爲 Toolbar 的時候,修改 elevation 的值 elevation: 1, //APP bar 的顏色,默認值爲 ThemeData.primaryColor。改值一般和下面的三個屬性一塊兒使用 backgroundColor: Colors.red, //App bar 的亮度,有白色和黑色兩種主題,默認值爲 ThemeData.primaryColorBrightness brightness:Brightness.light , //App bar 上圖標的顏色、透明度、和尺寸信息。默認值爲 ThemeData().primaryIconTheme iconTheme: ThemeData().primaryIconTheme, //App bar 上的文字主題。默認值爲 ThemeData().primaryTextTheme textTheme: ThemeData().accentTextTheme, //此應用欄是否顯示在屏幕頂部 primary: true, //標題是否居中顯示,默認值根據不一樣的操做系統,顯示方式不同,true居中 false居左 centerTitle: true, //橫軸上標題內容 周圍的間距 titleSpacing: NavigationToolbar.kMiddleSpacing, //展開高度 expandedHeight: 200, //是否隨着滑動隱藏標題 floating: true, //tab 是否固定在頂部 pinned: true, //與floating結合使用 snap: true, ) ]; } // //例子2 // @override // Widget build(BuildContext context) { // return Scaffold( // body:CustomScrollView( // slivers: <Widget>[ // const SliverAppBar( // pinned: true, // expandedHeight: 250.0, // flexibleSpace: FlexibleSpaceBar( // title: Text('Demo'), // ), // ), // SliverGrid( // gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( // maxCrossAxisExtent: 200.0, // mainAxisSpacing: 10.0, // crossAxisSpacing: 10.0, // childAspectRatio: 4.0, // ), // delegate: SliverChildBuilderDelegate( // (BuildContext context, int index) { // return Container( // alignment: Alignment.center, // color: Colors.teal[100 * (index % 9)], // child: Text('grid item $index'), // ); // }, // childCount: 20, // ), // ), // SliverFixedExtentList( // itemExtent: 50.0, // delegate: SliverChildBuilderDelegate( // (BuildContext context, int index) { // return Container( // alignment: Alignment.center, // color: Colors.lightBlue[100 * (index % 9)], // child: Text('list item $index'), // ); // }, // ), // ), // ], // ), // ); // } } class Choice { const Choice({ this.title, this.icon }); final String title; final IconData icon; } const List<Choice> choices = const <Choice>[ const Choice(title: 'Car', icon: Icons.directions_car), const Choice(title: 'Bicycle', icon: Icons.directions_bike), const Choice(title: 'Boat', icon: Icons.directions_boat), const Choice(title: 'Bus', icon: Icons.directions_bus), const Choice(title: 'Train', icon: Icons.directions_railway), const Choice(title: 'Walk', icon: Icons.directions_walk), ]; class ChoiceCard extends StatelessWidget { const ChoiceCard({ Key key, this.choice }) : super(key: key); final Choice choice; @override Widget build(BuildContext context) { final TextStyle textStyle = Theme.of(context).textTheme.display1; Widget _itemBuilder(BuildContext context,int index){ return ListTile( leading: Icon(choice.icon), title: Text("this is a " + choice.title), ); } return new Card( color: Colors.white, child: Center( child: ListView.builder( itemBuilder: _itemBuilder, itemCount: 30, ), ), // body: Center( // child: ListView.builder( // itemBuilder: _itemBuilder, // itemCount: 100, // // ), // )), // child: new Center( // child: new Column( // mainAxisSize: MainAxisSize.min, // crossAxisAlignment: CrossAxisAlignment.center, // children: <Widget>[ // new Icon(choice.icon, size: 128.0, color: textStyle.color), // new Text(choice.title, style: textStyle), // ], // ), // ), ); } } 複製代碼
相關文章
相關標籤/搜索