Flutter 开发之组件一

Flutter 的口号:一切谐为组件。同其他平台一样,Flutter 提供了一系列的组件,有基础组件(Basics Widgets),质感组件(Material Components)、Cupertino 等。



Flutter 中基础组件的介绍,用法也比较简单。每个组件都是一个以类的形式存在。Flutter 的组件属性也很多,我们不可能记得每一项,只有经常使用或者了解一些关键属性,然后用到时再去查看具体属性。正所谓“流水的属性,铁打的组件”。

本篇主要介绍以下几个组件:

  • Align-Align – 对齐组件
  • Bar – 组件
  • Box – 组件
  • Button – 组件

一、Align-Align – 对齐组件

一个 widget,它可以将其子 widget 对齐,并可以根据子 widget 的大小自动调整大小。


Align

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Align组件',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Align组件'),
        ),
        body:Container(
//          width: 200.0,
//          height: 200.0,
          color: Colors.red,
          child: Align(
            //对齐方式
            //alignment: Alignment.bottomLeft,
            //对齐方式使用x,y来表示 范围是-1.0 - 1.0
            alignment: Alignment(-0.5,-1.0),
            //宽高填充的系数
            widthFactor: 3.0,
            heightFactor: 3.0,
            child: Container(
              color: Colors.green,
              width: 100.0,
              height: 50.0,
              child: Text('align',style: TextStyle(color: Colors.white),),
            ),
          ),
        ),
      ),
    );
  }
}

二、Bar – 组件

2.1 AppBar 组件

状态栏上的右侧或左侧按钮,一个 Material Design 应用程序栏,由工具栏和其他可能的 widget(如 TabBar 和 FlexibleSpaceBar)组成。


AppBar

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'AppBar组件',
      home: Scaffold(
        appBar: AppBar(
          title: Text('标题'),
          //左侧图标
          leading: Icon(Icons.home),
          //背景色
          backgroundColor: Colors.green,
          //居中标题
          centerTitle: true,
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.print),
              tooltip: '打印',
              onPressed: (){},
            ),
            //菜单按钮
            PopupMenuButton<String>(
              itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[
                //菜单项
                PopupMenuItem<String>(
                  value: 'friend',
                  child: Text('分享到朋友圈'),
                ),
                PopupMenuItem<String>(
                  value: 'download',
                  child: Text('下载到本地'),
                ),
              ],
            ),
          ],
        ),
        body: Container(),
      ),
    );
  }
}

2.2 bottomNavigationBar

底部导航条,可以很容易地在 tap 之间切换和浏览顶级视图。


BottomNavigationBar

    return BottomNavigationBar(
      //底部按钮类型 固定样式
      type: BottomNavigationBarType.fixed,
      //按钮大小
      iconSize: 24.0,
      //点击里面的按钮回调的函数
      onTap: _onItemTapped,
      //当前选中项索引 高亮显示
      currentIndex: _currentIndex,
      //当类型为fixed时,选中项的颜色
      fixedColor: Colors.red,
      items: <BottomNavigationBarItem>[
        BottomNavigationBarItem(title: Text('聊天'),icon: Icon(Icons.chat)),
        BottomNavigationBarItem(title: Text('朋友圈'),icon: Icon(Icons.refresh)),
        BottomNavigationBarItem(title: Text('我的'),icon: Icon(Icons.person)),
      ],
    );

2.3 ButtonBar

未端对齐按钮容器 ButtonBar

      child: ButtonBar(
        //对齐方式 默认为末端end
        alignment: MainAxisAlignment.spaceAround,
      ),

2.4 FlexibleSpaceBar

可折叠的应用栏 FlexibleSpaceBar

        body: NestedScrollView(
            headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled){
              return <Widget>[
                SliverAppBar(
                  //展开高度
                  expandedHeight: 150.0,
                  //是否随着滑动隐藏标题
                  floating: false,
                  //是否固定在顶部
                  pinned: true,
                  //可折叠的应用栏
                  flexibleSpace: FlexibleSpaceBar(
                    centerTitle: true,
                    title: Text(
                      '可折叠的组件',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 16.0,
                      ),
                    ),
                  ),
                ),
              ];
            },
            body: Center(
              child: Text('向上提拉,查看效果'),
            )
        ),
      ),
    );

2.5 SliverAppBar

Sliver应用栏 SliverAppBar

 body: NestedScrollView(
            headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled){
              return <Widget>[
                SliverAppBar(
                  //是否预留高度
                  primary:true,
                  //标题前面显示的一个控件
                  leading: Icon(Icons.home),
                  //操作按钮
                  actions: <Widget>[
                    Icon(Icons.add),
                    Icon(Icons.print),
                  ],
                  //设置阴影值
                  elevation: 10.0,
                  //是否固定在顶部
                  pinned: true,
                  //可扩展区域高度
                  expandedHeight: 200.0,
                  //与floating结合使用
                  snap: false,
                  //是否随着滑动隐藏标题
                  floating: false,
                  //扩展区域
                  flexibleSpace: FlexibleSpaceBar(
                    centerTitle: true,
                    title: Text(
                      '这是一个很酷的标题',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 16.0,
                      ),
                    ),
                  ),
                ),
              ];
            },
            body: Center(
              child: Text(
                '拖动试试'
              ),
            ),
        ),

2.6 SnackBar

屏幕底部消息

return Center(
      child: GestureDetector(
        onTap: () {
          final snackBar = new SnackBar(
            //提示信息
            content: Text('这是一个SnackBar'),
            //背景色
            backgroundColor: Colors.green,
            //操作
            action: SnackBarAction(
              textColor: Colors.white,
              label: '撤消',
              onPressed: () {},
            ),
            //持续时间
            duration: Duration(minutes: 1),
          );
          Scaffold.of(context).showSnackBar(snackBar);
        },
        child: Text('显示屏幕底部消息'),
      ),
    );

2.7 TabBar

选项卡,一个显示水平选项卡的 Material Design widget。


TabBar

class DemoPageState extends State<DemoPage> with SingleTickerProviderStateMixin {

  ScrollController _scrollViewController;
  TabController _tabController;

  @override
  void initState(){
    super.initState();
    _scrollViewController = new ScrollController();
    //长度要和展示部分的Tab数一致
    _tabController = new TabController(vsync: this,length: 6);
  }

  @override
  void dispose(){
    super.initState();
    _scrollViewController.dispose();
    _tabController.dispose();
    super.dispose();
  }


  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 500.0,
      child: Scaffold(
        appBar: AppBar(
          title: Text('选项卡'),
          //前置图标
          leading: Icon(Icons.home),
          //应用栏背景色
          backgroundColor: Colors.green,
          //选项卡
          bottom: TabBar(
            controller: _tabController,
            //是否可以滚动
            isScrollable: true,
              tabs: <Widget>[
                Tab(text: '科技',icon: Icon(Icons.camera),),
                Tab(text: '房产',icon: Icon(Icons.print),),
                Tab(text: '体育',icon: Icon(Icons.favorite),),
                Tab(text: '娱乐',icon: Icon(Icons.share),),
                Tab(text: '电影',icon: Icon(Icons.video_call),),
                Tab(text: '教育',icon: Icon(Icons.airline_seat_flat_angled),),
              ]
          ),
        ),
        //选项卡视图
        body: TabBarView(controller: _tabController,
            children: <Widget>[
              Text('选项卡1'),
              Text('选项卡2'),
              Text('选项卡3'),
              Text('选项卡4'),
              Text('选项卡5'),
              Text('选项卡6'),
            ]
        ),
      ),
    );
  }
}

三、Box – 组件

3.1 ConstrainedBox

限定最大最小宽高容器,对其子项施加附加约束的 widget


ConstrainedBox

              //添加一个指定大小的盒子,限定其最大最小宽高
              ConstrainedBox(
                constraints: const BoxConstraints(
                  minWidth: 100.0,
                  minHeight: 20.0,
                  maxHeight: 60.0,
                  maxWidth: 200.0,
                ),
                child: Container(
                  width: 250,
                  height: 80,
                  child: Text(
                    'width>maxWidth height>maxHeight',
                    style: TextStyle(color: Colors.white),
                  ),
                  color: Colors.green,
                ),
              ),

3.2 DecoratedBox

装饰容器,DecoratedBox 可以在其子 widget 绘制前(或后)绘制一个装饰 Decoration(如背景、边框、渐变等)。

DecoratedBox

            //添加装饰
            child: DecoratedBox(
                //装饰定位 DecorationPosition.background背景模式 DecorationPosition.foreground前景模式
                position: DecorationPosition.background,
                decoration: BoxDecoration(
                  //背景色
                  color: Colors.grey,
                  //设置背景图片
                  image: DecorationImage(
                    //图片填充方式
                    fit: BoxFit.cover,
                    image: ExactAssetImage('assets/view.jpeg'),
                  ),
                  //边框弧度
                  //borderRadius: BorderRadius.circular(10.0),
                  border: Border.all(
                    //边框颜色
                    color: Colors.red,
                    //边框粗细
                    width: 6.0,
                  ),
                  //边框样式
                  shape: BoxShape.rectangle,
                ),
              child: Text('定位演示',style: TextStyle(fontSize: 36.0,color: Colors.green),),
            ),

3.3 FittedBox

填充容器,按自己的大小调整其子 widget 的大小和位置。 FittedBox

/*
          BoxFit.fill  //全部显示,显示可能拉伸,充满
          BoxFit.contain    //全部显示,显示原比例,不需充满
          BoxFit.cover    //显示可能拉伸,可能裁剪,充满
          BoxFit.fitWidth    //显示可能拉伸,可能裁剪,宽度充满
          BoxFit.fitHeight    //显示可能拉伸,可能裁剪,高度充满
          BoxFit.none
          BoxFit.scaleDown   //效果和contain差不多,但是此属性不允许显示超过源图片大小,可小不可大
*/

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'FittedBox填充容器',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('FittedBox填充容器'),
        ),

        body: Center(
          child: Column(
            children: <Widget>[
            Container(
                width: 300.0,
                height: 300.0,
                color: Colors.grey,
                child: FittedBox(
                  //填充类型
                  fit: BoxFit.none,
                  //居中对齐
                  alignment: Alignment.center,
                  child: Image.asset('assets/view.jpeg'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

3.4 OverflowBox

溢出容器,对其子项施加不同约束的 widget,它可能允许子项溢出父级。 OverflowBox

          //溢出容器
          child: OverflowBox(
            //对齐方式
            alignment: Alignment.topLeft,
            //限制条件
            maxWidth: 300.0,
            maxHeight: 500.0,
            child: Container(
              color: Colors.blueGrey,
              width: 400.0,
              height: 400.0,
            ),
          ),

3.5 RotatedBox

旋转容器,可以延顺时针以90度的倍数旋转其子 widget。RotatedBox

        body: Center(
          child: Column(
            children: <Widget>[

              SizedBox(
                height: 20.0,
              ),
              RotatedBox(
                child: Text('ABCDE',style: TextStyle(fontSize: 28.0),),
                //旋转次数 每次旋转一圈的1/4
                quarterTurns: 1,
              ),

              SizedBox(
                height: 20.0,
              ),
              RotatedBox(
                child: Text('ABCDE',style: TextStyle(fontSize: 28.0),),
                quarterTurns: 2,
              ),

              SizedBox(
                height: 20.0,
              ),
              RotatedBox(
                child: Text('ABCDE',style: TextStyle(fontSize: 28.0),),
                quarterTurns: 3,
              ),

              SizedBox(
                height: 20.0,
              ),
              RotatedBox(
                child: Text('ABCDE',style: TextStyle(fontSize: 28.0),),
                quarterTurns: 4,
              ),
            ],
          ),
        ),

3.6 SizedBox

指定宽高容器,一个特定大小的盒子。这个 widget 强制它的孩子有一个特定的宽度和高度。如果宽度或高度为 NULL,则此 widget 将调整自身大小以匹配该维度中的孩子的大小。


SizedBox

        body:Center(
          //指定宽高容器 child不允许超出指定大小的范围
          child: SizedBox(
            width: 200.0,
            height: 200.0,
            //限定图片大小
            child: Image.asset('assets/cat.jpeg'),
            //子元素
//            child: Container(
//              width: 10.0,
//              height: 10.0,
//              color: Colors.green,
//            ),
          ),
        ),

四、Button – 组件

4.1 DropdownButton

下拉按钮 DropdownButton

class DropdownButtonDemo extends StatelessWidget {

  List<DropdownMenuItem> generateItemList(){
    final List<DropdownMenuItem> items = new List();
    final DropdownMenuItem item1 = new DropdownMenuItem(child: Text('北京'),value: '北京',);
    final DropdownMenuItem item2 = new DropdownMenuItem(child: Text('上海'),value: '上海',);
    final DropdownMenuItem item3 = new DropdownMenuItem(child: Text('广州'),value: '广州',);
    final DropdownMenuItem item4 = new DropdownMenuItem(child: Text('深圳'),value: '深圳',);

    items.add(item1);
    items.add(item2);
    items.add(item3);
    items.add(item4);

    return items;
  }


  @override
  Widget build(BuildContext context) {

    return DropdownButton(
      //提示文本
      hint: Text('请选择一个城市'),
      //下拉列表项数据
      items: generateItemList(),
      value: selectItemValue,
      //下拉三角型图标大小
      iconSize: 48.0,
      //下拉文本样式
      style: TextStyle(
        color: Colors.green,
      ),
      //设置阴影高度
      elevation: 24,
      //将下拉框设置为水平填充成父级
      isExpanded: true,
      //下拉改变事件
      onChanged: (T){
        var obj = T;
      },
    );
  }
}

4.2 FlatButton

一个扁平的 Material 按钮.


FlatButton

            FlatButton.icon(
                onPressed: (){

                },
                icon: Icon(Icons.print,size: 36.0,),
                label: Text('默认按钮',style: TextStyle(fontSize: 36.0),),
            ),

           FlatButton(
              //文本
              child: Text(
                'Success',
                style: TextStyle(fontSize: 26.0),
              ),
              //按钮背景色
              color: Colors.green,
              //按钮亮度
              colorBrightness: Brightness.dark,
              //失效时的背景色
              disabledColor: Colors.grey,
              //失效时的文本色
              disabledTextColor: Colors.grey,
              //文本颜色
              textColor: Colors.white,
              //按钮主题 ButtonTheme ButtonThemeData ButtonTextTheme ThemeData
              textTheme: ButtonTextTheme.normal,
              //墨汁飞溅的颜色
              splashColor: Colors.blue,
              //抗锯齿能力
              clipBehavior: Clip.antiAlias,
              //内边距
              padding: new EdgeInsets.only(
                bottom: 5.0,
                top: 5.0,
                left: 20.0,
                right: 20.0,
              ),
            ),

4.3 FloatingActionButton

跟 iOS 手机的小白点一样,一个圆形图标按钮,它悬停在内容之上,以展示应用程序中的主要动作。FloatingActionButton 通常用于Scaffold.floatingActionButton 字段。


FloatingActionButton

            FloatingActionButton(
              //图标
              child: const Icon(Icons.person),
              //提示信息
              tooltip: '这是一个自定义的按钮',
              //背景色
              backgroundColor: Colors.blue,
              //前景色
              foregroundColor: Colors.white,
              //hero效果使用
              heroTag: null,
              //未点击时的阴影
              elevation: 8.0,
              //点击时的阴影
              highlightElevation: 16.0,
              onPressed: () {},
              // 是否为“mini”类型,默认为false,FAB 分为三种类型:regular, mini, and extended
              mini: false,

              //圆角方形的样式
              shape: RoundedRectangleBorder(
                side: BorderSide(
                  width: 2.0,
                  color: Colors.white,
                  style: BorderStyle.solid,
                ),
                borderRadius: BorderRadius.only(
                  topRight: Radius.circular(8.0),
                  topLeft: Radius.circular(8.0),
                  bottomRight: Radius.circular(8.0),
                  bottomLeft: Radius.circular(8.0),
                ),
              ),
            ),

4.4 IconButton

一个 Material 图标按钮,点击时会有水波动画。



IconButton

           child: IconButton(
              //图标
              icon: Icon(Icons.print),
              //图标大小
              iconSize: 48.0,
              //根据父容器来决定图标的位置
              alignment: AlignmentDirectional.center,
              color: Colors.green,
              //墨汁飞溅效果
              splashColor: Colors.blue,
              padding: EdgeInsets.only(bottom: 5.0, top: 5.0, left: 30.0, right: 30.0),
              //提示文本
              tooltip: '一个打印图标',
              //按下
              onPressed: () {},
            ),

4.5 RaisedButton

Material Design 中的 button, 一个凸起的材质矩形按钮。



RaisedButton

     child: RaisedButton(
        //文本
        child: Text(
          '点击登录按钮',
          style: TextStyle(fontSize: 26.0),
        ),
        //按钮背景色
        color: Colors.green,
        //按钮亮度
        colorBrightness: Brightness.dark,
        //失效时的背景色
        disabledColor: Colors.grey,
        //失效时的文本色
        disabledTextColor: Colors.grey,
        //文本颜色
        textColor: Colors.white,
        //按钮主题 ButtonTheme ButtonThemeData ButtonTextTheme ThemeData
        textTheme: ButtonTextTheme.normal,
        //墨汁飞溅的颜色
        splashColor: Colors.blue,
        //抗锯齿能力
        clipBehavior: Clip.antiAlias,
        //内边距
        padding: new EdgeInsets.only(
          bottom: 5.0,
          top: 5.0,
          left: 20.0,
          right: 20.0,
        ),
        shape: RoundedRectangleBorder(
          side: new BorderSide(
            width: 2.0,
            color: Colors.white,
            style: BorderStyle.solid,
          ),
          borderRadius: BorderRadius.only(
            topRight: Radius.circular(10.0),
            topLeft: Radius.circular(10.0),
            bottomLeft: Radius.circular(10.0),
            bottomRight: Radius.circular(10.0),
          ),
        ),

        onPressed: () {
          print('按钮按下操作');
        },
      ),

4.6 RawMaterialButton

RawMaterialButton

     body: RawMaterialButton(
          onPressed: (){},
          textStyle: TextStyle(fontSize: 28.0,color: Colors.black,),
          //文本
          child: Text('RawMaterialButton组件'),
          //高亮时的背景色
          highlightColor: Colors.red,
          //墨汁飞溅
          splashColor: Colors.blue,
          //搞锯齿
          clipBehavior: Clip.antiAlias,
          padding: EdgeInsets.only(bottom: 5.0,top: 5.0,left: 30.0,right: 30.0),
          //高亮时的阴影
          highlightElevation: 10.0,
        ),

待续