Flutter 开发之组件三

Flutter 一切谐为组件!



本篇主要涉及的组件有:

  • Menu - 菜单
  • Picker - 日期时间组件
  • Progress - ProgressIndicator - 进度条组件
  • Radio
  • Scanffold - Material 布局组件
  • Scroll - PageView - 滑动页面
  • Slider - 滑块
  • Spacing - AnimatedPadding - 带动画的内边距
  • Stack - 层叠组件
  • Switch
  • Table - 表格组件
  • Text
  • Theme - MaterialApp - Material 应用

一、Menu - 菜单

1.1 CheckedPopupMenuItem - 选中弹出菜单

dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^0.1.2
  image_picker: ^0.4.10
  fluttertoast: ^2.2.2
class DemoPageState extends State<DemoPage> {

  //已选择的菜单项
  List<String> _checkedValues;

  final String _checkedValue1 = 'One';
  final String _checkedValue2 = 'Two';
  final String _checkedValue3 = 'Three';
  final String _checkedValue4 = 'Four';

  @override
  void initState(){
    super.initState();
    //初始化已选中的项
    _checkedValues = <String>[_checkedValue2];
  }

  //检测传入的值是否在_checkedValues里
  bool isChecked(String value) => _checkedValues.contains(value);

  void showCheckedMenuSelections(String value){
    if(_checkedValues.contains(value)){
      _checkedValues.remove(value);
    }else{
      _checkedValues.add(value);
    }
    showInSnackBar('Checked $_checkedValues');
  }

  //弹出已选择的项
  void showInSnackBar(String value){
    Fluttertoast.showToast(
        msg: value,
      toastLength: Toast.LENGTH_SHORT,
      backgroundColor: Colors.grey,
      textColor: Colors.white,
    );
  }


  @override
  Widget build(BuildContext context) {
     return Container(
       color: Theme.of(context).primaryColor,
       child: ListTile(
         title: Text('有选择标记的弹出菜单',style: TextStyle(color: Colors.white),),
         trailing: PopupMenuButton<String>(
           padding: EdgeInsets.zero,
           onSelected: showCheckedMenuSelections,
           //弹出按钮图标
           icon: Icon(Icons.menu,color: Colors.white,),
           itemBuilder: (BuildContext context) =><PopupMenuItem<String>>[
             //有选择标记的弹出菜单项
              CheckedPopupMenuItem<String>(
                value: _checkedValue1,
                checked: isChecked(_checkedValue1),
                child: Text(_checkedValue1),
              ),
              CheckedPopupMenuItem<String>(
                value: _checkedValue2,
                //当前项是否可点击
                enabled: false,
                //当前项是否被选中
                checked: isChecked(_checkedValue2),
                child: Text(_checkedValue2),
              ),
              CheckedPopupMenuItem<String>(
                value: _checkedValue3,
                checked: isChecked(_checkedValue3),
                child: Text(_checkedValue3),
              ),
              CheckedPopupMenuItem<String>(
                value: _checkedValue4,
                checked: isChecked(_checkedValue4),
                child: Text(_checkedValue4),
              ),
           ],
         ),
       ),
     );
  }

}

1.2 DropdownMenuItem - 下拉菜单项

class DemoPageState extends State<DemoPage> {

  String dropdownValue = 'One';

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ListTile(
        title: Text('下拉菜单按钮'),
        trailing: DropdownButton(
          value: dropdownValue,
          onChanged: (String val) {
            setState(() {
              dropdownValue = val;
            });
          },
          //渲染所有菜单项
          items: <String>['One','Two','Three','Four'].map<DropdownMenuItem<String>>((String value){
            //渲染每一个可选项
            return DropdownMenuItem<String>(
              value: value,
              child: Text(value),
            );
          }).toList(),
        ),
      ),
    );

  }

}

1.3 PopupMenuButton - 弹出菜单按钮

当菜单隐藏式,点击或调用onSelected时显示一个弹出式菜单列表


PopupMenuButton

class DemoPageState extends State<DemoPage> {

  void printSelectValue(String value){
    print(value);
  }

  @override
  Widget build(BuildContext context) {

    return Container(
      child: ListTile(
        title: Text('弹出菜单按钮'),
        //弹出菜单按钮
        trailing: PopupMenuButton<String>(
          padding: EdgeInsets.zero,
          //选择回调
          onSelected: printSelectValue,
          //菜单项构造器
          itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
            //弹出菜单项
            PopupMenuItem<String>(
              value: '锁定会议',
              child: ListTile(
                leading: Icon(Icons.lock),
                title: Text('锁定会议'),
              ),
            ),
            PopupMenuItem<String>(
              value: '挂断会议',
              child: ListTile(
                leading: Icon(Icons.phone),
                title: Text('挂断会议'),
              ),
            ),
            //弹出菜单分隔线
            PopupMenuDivider(),
            PopupMenuItem<String>(
              value: '全部静音',
              child: ListTile(
                leading: Icon(Icons.volume_mute),
                title: Text('全部静音'),
              ),
            ),
          ],
        ),
      ),
    );

  }

}

二、Picker - 日期时间组件

日期&时间选择器


Date & Time Pickers

class DemoPageState extends State<DemoPage> {

  DateTime _date = new DateTime.now();
  TimeOfDay _time = new TimeOfDay.now();

  Future<void> _selectDate(BuildContext context) async {
    final DateTime picked = await showDatePicker(
        context: context,
        //初始日期
        initialDate: _date,
        //起始日期
        firstDate: DateTime(2019,1),
        //结束日期
        lastDate: DateTime(2020));
        if(picked != null && picked != _date){
          print('当前选择的日期是:${_date.toString()}' );
        }
        setState(() {
          _date = picked;
        });


        if(picked == null){
          _date = new DateTime.now();
        }

  }


  Future<void> _selectTime(BuildContext context) async {
    final TimeOfDay picked = await showTimePicker(
        context: context,
      initialTime: _time,
    );
    if(picked != null && picked != _time){
      print('当前选择的时间是:${_time.toString()}' );
    }
    setState(() {
      _time = picked;
    });


    if(picked == null){
      _time = new TimeOfDay.now();
    }

  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: <Widget>[
          Text('日期选择'),
          RaisedButton(
            child: Text('日期选择结果:${_date.toString()}'),
            onPressed: (){
              _selectDate(context);
            },
          ),
          Text('时间选择'),
          RaisedButton(
            child: Text('时间选择结果:${_time.toString()}'),
            onPressed: (){
              _selectTime(context);
            },
          ),
        ],
      ),
    );
  }

}

三、Progress - ProgressIndicator - 进度条组件

class DemoPageState extends State<DemoPage> {

  @override
  Widget build(BuildContext context) {
      return Center(
        child: Column(
          children: <Widget>[

            SizedBox(
              height: 100.0,
            ),

            CircularProgressIndicator(
              //背景色
              backgroundColor: Colors.red,
              //进度值的颜色
              valueColor: AlwaysStoppedAnimation(Colors.yellow),
              //当前进度值
              value: 0.5,
            ),

            SizedBox(
              height: 100.0,
            ),

            LinearProgressIndicator(
              backgroundColor: Colors.red,
              valueColor: AlwaysStoppedAnimation(Colors.yellow),
              value: 0.3,
            ),
          ],
        ),
      );
  }
}

四、Radio

4.1 Radio

单选框,允许用户从一组中选择一个选项。


Radio

class DemoPageState extends State<DemoPage> {

  int groupValue = 1;

  @override
  Widget build(BuildContext context) {
    return Column(
      //次轴居中
      crossAxisAlignment: CrossAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,

      children: <Widget>[
        Radio(
          //控件颜色
          activeColor: Colors.red,
          //值
          value: 1,
          //当value与groupValue一致时选中
          groupValue: groupValue,
          onChanged: (T){
            this.setState((){
              groupValue = T;
            });
          },
        ),
        Radio(
          value: 2,
          groupValue: groupValue,
          onChanged: (T){
            this.setState((){
              groupValue = T;
            });
          },
        ),
        Radio(
          value: 3,
          groupValue: groupValue,
          onChanged: (T){
            this.setState((){
              groupValue = T;
            });
          },
        ),
      ],
    );
  }
}

4.2 RadioListTitle

比 Radio 组件更丰富些

class DemoPageState extends State<DemoPage> {

  String value = '2';

  onChange(v){
    this.setState((){
      value = v;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        RadioListTile<String>(
          //标题
          title: const Text('星期一'),
          //值
          value: '1',
          //右侧图标
          secondary: Icon(Icons.print),
          //当value及groupValue相等时处于选中状态
          groupValue: this.value,
          //是否显示三个
          isThreeLine: false,
          subtitle: const Text('Monday'),
          onChanged: onChange,
        ),
        RadioListTile<String>(
          //标题
          title: const Text('星期二'),
          //值
          value: '2',
          secondary: Icon(Icons.book),
          //当value及groupValue相等时处于选中状态
          groupValue: this.value,
          //是否显示三个
          isThreeLine: false,
          subtitle: const Text('Tuesday'),
          onChanged: onChange,
        ),
      ],
    );
  }
}

五、Scanffold - Material 布局组件

Material Design 布局结构的基本实现。此类提供了用于显示 drawer、snackbar 和底部 sheet 的 API。


Scanffold

class DemoPageState extends State<DemoPage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //应用栏
      appBar: AppBar(
        backgroundColor: Colors.red,
        title: Text('标题',style: TextStyle(color: Colors.white),),
        centerTitle: true,
        elevation: 10.0,
        leading: Icon(Icons.home),
        actions: <Widget>[
          Icon(Icons.add),
        ],
        bottom: PreferredSize(
            child: Container(
              height: 50.0,
              child: Center(
                child: Text('显示在标题下面的内容'),
              ),
              decoration: BoxDecoration(
                color: Colors.redAccent,
              ),
            ),
            preferredSize: Size.fromHeight(50.0),
        ),
      ),

      //内容区域
      body: Center(
        child: Text('中间内容部分',style: TextStyle(color: Colors.red,fontSize: 36.0),),
      ),

      //侧边栏 抽屉组件
      drawer: Drawer(
        child: Center(
          child: Container(
            width: 150.0,
            color: Colors.orange,
            child: Text('侧边栏',style: TextStyle(color: Colors.white,fontSize: 24.0),),
          ),
        )
      ),

      //底部 持久化按钮
      persistentFooterButtons: <Widget>[
        Icon(Icons.person),
        Icon(Icons.add),
        Icon(Icons.print),
        Icon(Icons.apps),
        Icon(Icons.chat),
      ],

      //底部 导航按钮
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: 1,
        fixedColor: Colors.redAccent,
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('主页'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.chat),
            title: Text('聊天'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            title: Text('我的'),
          ),
        ],
      ),

      //底部 FAB按钮
      floatingActionButton: Builder(
          builder: (BuildContext context){
            return FloatingActionButton(
              backgroundColor: Colors.red,
              child: Icon(Icons.add),
              onPressed: (){
                var snackbar = new SnackBar(
                    content: Text('显示SnackBar'),
                  backgroundColor: Colors.red,
                  duration: Duration(
                    milliseconds : 1500,
                  ),
                  action: SnackBarAction(
                      label: '撤销',
                      onPressed: (){}
                  ),
                );

                Scaffold.of(context).showSnackBar(snackbar);
              },
            );
          }
      ),
    );
  }
}

六、Scroll - PageView - 滑动页面

class DemoPageState extends State<DemoPage> {

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 400.0,
      //滚动页面
      child: PageView(
        //翻滚方向
        scrollDirection: Axis.vertical,
        children: <Widget>[
          Container(
            color: Colors.redAccent,
            child: Center(
              child: Text('这是第一页',style: TextStyle(color: Colors.white,fontSize: 28.0),),
            ),
          ),
          Container(
            color: Colors.blue,
            child: Center(
              child: Text('这是第二页',style: TextStyle(color: Colors.white,fontSize: 28.0),),
            ),
          ),
          Container(
            color: Colors.orange,
            child: Center(
              child: Text('这是第三页',style: TextStyle(color: Colors.white,fontSize: 28.0),),
            ),
          ),
        ],
      ),
    );
  }
}

七、Slider - 滑块主题

7.1 Slider - 滑块

滑块,允许用户通过滑动滑块来从一系列值中选择。


Slider

class DemoPageState extends State<DemoPage> {

  double value = 0.0;

  @override
  Widget build(BuildContext context) {
      return Slider(
        //实际进度的位置
        value: value,
        min: 0.0,
        max: 100.0,
        label: '当前音量是:$value',
        //进度中活动部分的颜色
        activeColor: Colors.green,
        //进度中未活动部分的颜色
        inactiveColor: Colors.black,
        //分量的个数 划分成多少块
        divisions: 1000,
        //拖动改变回调
        onChanged: (val){
          setState(() {
            value = val.roundToDouble();
          });
        },
        //每滑动一次结果时回调
        onChangeEnd: (val){
          print('onChangeEnd');
        },
        //每滑动一次开始时回调
        onChangeStart: (val){
          print('onChangeStart');
        },
      );
  }
}

7.2 SliderTheme - 滑块主题

class DemoPageState extends State<DemoPage> {

  double value = 0.0;

  @override
  Widget build(BuildContext context) {
    return SliderTheme(
      data: SliderTheme.of(context).copyWith(
        //已拖动的颜色
        activeTrackColor: Colors.greenAccent,
        //未拖动的颜色
        inactiveTrackColor: Colors.green,

        //提示进度的气泡的背景色
        valueIndicatorColor: Colors.green,
        //提示进度的气泡文本的颜色
        valueIndicatorTextStyle: TextStyle(
          color:Colors.white,
        ),

        //滑块中心的颜色
        thumbColor: Colors.blueAccent,
        //滑块边缘的颜色
        overlayColor: Colors.white,

        //divisions对进度线分割后,断续线中间间隔的颜色
        inactiveTickMarkColor: Colors.white,

      ),
      child: Slider(
        value: value,
        label: '$value',
        min: 0.0,
        max: 100.0,
        divisions: 10,
        onChanged: (val){
          setState(() {
            value = val.floorToDouble();//转化成double
          });
        },
      ),
    );
  }
}

八、Spacing

8.1 AnimatedPadding - 带动画的内边距

class DemoPageState extends State<DemoPage> {
  double paddingValue = 10.0;

  _changePaddingValue() {
    if (paddingValue == 10.0) {
      setState(() {
        paddingValue = 50.0;
      });
    } else {
      setState(() {
        paddingValue = 10.0;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: <Widget>[
          Container(
            width: 300.0,
            height: 300.0,
            color: Colors.redAccent,
            //带动画的内边距
            child: AnimatedPadding(
              //均衡的内边距
              padding: EdgeInsets.symmetric(
                //水平及垂直方向的边距值
                horizontal: paddingValue,
                vertical: paddingValue,
              ),
              //动画时长
              duration: const Duration(milliseconds: 100),
              //动画类型
              curve: Curves.bounceIn,
              child: Container(
                height: 200.0,
                color: Colors.greenAccent,
              ),
            ),
          ),
          RaisedButton(
            onPressed: _changePaddingValue,
            child: Text('点击切换内边距'),
          ),
        ],
      ),
    );
  }
}

8.2 Padding - 内边距

一个 widget, 会给其子 widget 添加指定的填充。


Padding

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Padding组件',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Padding组件'),
        ),
        body:Center(
          //父容器
          child: Container(
            width: 300.0,
            height: 300.0,
            color: Colors.grey,
            //内边距
            //padding: const EdgeInsets.all(30.0),
            //根据left top right bottom分别设置内边距
            //padding: const EdgeInsets.only(left:10.0, top:20.0,right:30.0, bottom:40.0),
            padding: const EdgeInsets.fromLTRB(10.0, 20.0,30.0, 40.0),
            //子容器
            child: Container(
              color: Colors.green,
            ),
          ),
        ),
      ),
    );
  }
}

九、Stack - 层叠组件

9.1 IndexedStack - 索引层叠组件

从一个子 widget 列表中显示单个孩子的 Stack。IndexedStack

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {

  final int currentIndex = 2;

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'IndexedStack组件',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('IndexedStack组件'),
        ),
        body: IndexedStack(
          //当前显示内容的索引
          index: currentIndex,
          children: <Widget>[
            //圆形头像0
            CircleAvatar(
              backgroundColor: Colors.green,
              radius: 50.0,
            ),
            //添加文本的容器1
            Container(
              decoration: BoxDecoration(
                color: Colors.black12,
              ),
              child: Text(
                'IndexedStack',
                style: TextStyle(
                  fontSize: 20.0,
                  fontWeight: FontWeight.bold,
                  color: Colors.red,
                ),
              ),
            ),
            //添加一个图标2
            Icon(
              Icons.lock,
              size: 48.0,
              color: Colors.green,
            ),
          ],
        ),
      ),
    );
  }
}

9.2 Stack - 层叠组件

可以允许其子 widget 简单的堆叠在一起,谁后面添加,谁在上面。


Stack

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      //是否显示 debug 标签
      debugShowCheckedModeBanner: false,
      title: "Stack组件",
      home: Scaffold(
        appBar: AppBar(
          title: Text("Stack组件"),
        ),
        body:Column(
          children: <Widget>[
            Container(
              width: 300.0,
              height: 300.0,
              color: Colors.red,
              //层叠组件
              child: Stack(
                //对齐方式
                //子组件对齐方式,同 Container 的 alignment 属性一样的,它指定的是所有子组件的对齐方式,所以建议在只有两个子组件的时候
                //使用,如果有三个及以上的子组件时,建议使用 Positioned 包裹子组件来决定子组件的位置,alignment 的可选值有:
                //AlignmentDirectional.topCenter:垂直靠顶部水平居中对齐
                //AlignmentDirectional.topEnd:垂直靠顶部水平靠右对齐
                //AlignmentDirectional.centerStart:垂直居中水平靠左对齐
                //AlignmentDirectional.center:垂直和水平居中都对齐
                //AlignmentDirectional.bottomEnd:垂直居中水平靠右对齐
                //AlignmentDirectional.bottomStart:垂直靠底部水平靠左对齐
                //AlignmentDirectional.bottomCenter:垂直靠底部水平居中对齐
                //AlignmentDirectional.bottomEnd:垂直靠底部水平靠右对齐
                //也可以像我一样指定具体的偏移量,它是以整个组件的中心为坐标原点,x、y 偏移量取值范围为 [-1,1],如果 x 的偏移量大于 0
                //则表示向右偏移,小于 0 则向左偏移;如果 y 轴的偏移量大于 0 则向下偏移,小于 0 则向上偏移。
                alignment: AlignmentDirectional.center,
                //textDirection: TextDirection.ltr,
                //如何确定没有使用 Position 包裹的子组件的大小,可选值有:
                //StackFit.loose:子组件宽松取值,可以从 min 到 max
                //StackFit.expand:子组件取最大值
                //StackFit.passthrough:不改变子组件约束条件
                //fit: StackFit.loose,
                //超出部分的处理方式
                //overflow: Overflow.clip,
                children: <Widget>[

                  Container(
                    color: Colors.green,
                    width: 100.0,
                    height: 50,
                  ),

                  Text(
                    'Stack组件',
                    textDirection: TextDirection.ltr,
                    style: TextStyle(
                      fontSize: 20.0,
                      fontWeight: FontWeight.bold,
                      letterSpacing: 5.0,
                      color: Colors.white,
                    ),
                  ),

                  //定位方式
                  Positioned(
                    right: 10,
                    bottom: 30,
                    child: Text(
                      'A',
                      style: TextStyle(
                        fontSize: 36.0,
                        color: Colors.white,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

十、Switch

10.1 AnimatedSwitcher

class DemoPageState extends State<DemoPage> {

  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        //带动画的Switcher
        AnimatedSwitcher(
          //动画时长
          duration: const Duration(milliseconds: 500),
          //指定过渡动画
          transitionBuilder: (Widget child, Animation<double> animation){
            return ScaleTransition(child: child, scale: animation,);
          },
          //动画显示内容
          child: Text(
            '$_count',
            key: ValueKey<int>(_count),
            style: TextStyle(fontSize: 56.0),
          ),
        ),
        RaisedButton(
          child: const Text('点击+1'),
          onPressed: (){
            setState(() {
              _count +=1;
            });
          },
        ),
      ],
    );
  }
}

10.2 SwitchListTile

class DemoPageState extends State<DemoPage> {
  bool check = false;

  @override
  Widget build(BuildContext context) {
    return SwitchListTile(
      //激活时的颜色
      activeColor: Colors.red,
      value: check,
      onChanged: (bool val){
        this.setState((){
          this.check = val;
        });
      },
      //标题
      title: const Text('是否打印'),
      //添加图标
      secondary: const Icon(Icons.print),
      //子标题
      subtitle: const Text('打印一张照片'),
    );
  }
}

10.3 Switch

On/off 用于切换一个单一状态。


Switch

class DemoPageState extends State<DemoPage> {
  bool check = false;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Switch(
          //决定Switch打开还是关闭
          value: this.check,
          onChanged: (bool value) {
            this.setState(() {
              this.check = !this.check;
            });
          },
        ),
        Switch.adaptive(
          value: this.check,
          //激活时原点的颜色
          activeColor: Colors.red,
          onChanged: (bool value) {
            this.setState(() {
              this.check = !this.check;
            });
          },
        ),
        SizedBox(
          width: 100.0,
          height: 30.0,
          child: Switch(
            //决定Switch打开还是关闭
            value: this.check,
            //激活时原点的颜色
            activeColor: Colors.red,
            //激活时滑轨的颜色
            activeTrackColor: Colors.orange,
            //激活时按钮的背景图片
            activeThumbImage: NetworkImage('https://flutter.io/assets/homepage/news-1-2ab8ef4d7570c3e4f481fd839365fbfc11ea97bdb7fd9fb5fd38aa3348149136.png'),


            //非激活时原点的颜色
            inactiveThumbColor: Colors.green,
            //非激活时滑轨的颜色
            inactiveTrackColor: Colors.yellow,
            //非激活时按钮的背景图片
            inactiveThumbImage: NetworkImage('https://flutter.io/assets/homepage/news-2-599aefd56e8aa903ded69500ef4102cdd8f988dab8d9e4d570de18bdb702ffd4.png'),


            onChanged: (bool value) {
              this.setState(() {
                this.check = !this.check;
              });
            },
          ),
        ),

      ],
    );
  }
}

十一、Table - 表格组件

为其子 widget 使用表格布局算法的 widget。Table

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Table组件',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Table组件'),
        ),
        body: Center(
          child: Container(
            //表格
            child: Table(
              //所有列宽
              columnWidths: const {
                //列宽
                0: FixedColumnWidth(100.0),
                1: FixedColumnWidth(200.0),
                2: FixedColumnWidth(50.0),
              },
              //表格边框样式
              border: TableBorder.all(
                color: Colors.green,
                width: 2.0,
                style: BorderStyle.solid,
              ),
              children: [
                TableRow(
                  //第一行样式 添加背景色
                  decoration: BoxDecoration(
                    color: Colors.grey,
                  ),
                  children: [
                    //增加行高
                    SizedBox(
                      height: 30.0,
                      child: Text('姓名',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),),
                    ),

                    Text('性别',style: TextStyle(fontWeight: FontWeight.bold),),
                    Text('年龄',style: TextStyle(fontWeight: FontWeight.bold),),
                  ]
                ),
                TableRow(
                    children: [
                      Text('张三'),
                      Text('男'),
                      Text('20'),
                    ]
                ),
                TableRow(
                    children: [
                      Text('小红'),
                      Text('女'),
                      Text('28'),
                    ]
                ),
                TableRow(
                    children: [
                      Text('李四'),
                      Text('男'),
                      Text('28'),
                    ]
                ),
                TableRow(
                    children: [
                      Text('机器猫'),
                      SizedBox(
                        width: 88.0,
                        height: 88.0,
                        child: Image.asset('assets/cat.jpeg'),
                      ),

                      Text('26'),
                    ]
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

十二、Text

12.1 Text

单一格式的文本。


Text

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text组件',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Text组件'),
        ),
        body:Center(
          child:Column(
            children: <Widget>[

              Text(
                'hello',
                style: TextStyle(
                  color: Colors.red,
                  fontSize: 48.0,
                  decoration: TextDecoration.lineThrough,
                  decorationColor: Colors.black,
                ),
              ),


              Text(
                '下划线',
                style: TextStyle(
                  color: Colors.green,
                  fontSize: 48.0,
                  decoration: TextDecoration.underline,
                  decorationColor: Colors.black,
                ),
              ),

              Text(
                '虚线上划线+23号+倾斜',
                style: TextStyle(
                  color: Colors.orange,
                  fontSize: 23.0,
                  decoration: TextDecoration.overline,
                  decorationStyle: TextDecorationStyle.dashed,
                  decorationColor: Colors.red,
                ),
              ),

              Text(
                '36号+加粗',
                style: TextStyle(
                  color: Colors.blue,
                  fontSize: 36.0,
                  fontStyle: FontStyle.italic,
                  fontWeight: FontWeight.bold,
                  decorationColor: Colors.black,
                ),
              ),

              Text(
                '自定义字体',
                style: TextStyle(
                  color: Colors.blue,
                  fontSize: 36.0,
                  fontFamily: 'myfont',
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

12.2 RichText

富文本组件,表示多种样式的文本组件。RichText

import 'package:flutter/material.dart';

void main() {
  runApp(
      new MaterialApp(
        title: '富文本组件',
        home: new TextDemo(),
      )
  );
}

class TextDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Center(
      child: RichText(
          text: TextSpan(
            text: 'I ',
            style: TextStyle(fontSize:38.0,fontWeight: FontWeight.bold,),
            children: <TextSpan>[
              TextSpan(text: 'want ', style: TextStyle(fontSize:32.0,fontWeight: FontWeight.bold, color: Colors.red)),
              TextSpan(text: ' study', style: TextStyle(fontSize:32.0,fontStyle: FontStyle.italic)),
              TextSpan(text: ' flutter', style: TextStyle(fontSize:32.0,fontStyle: FontStyle.italic,color: Colors.green,)),
            ],
          ),

      ),
    );
  }
}

十三、Theme - MaterialApp - Material 应用

一个方便的 widget,它封装了应用程序实现 Material Design 所需要的一些 widget。


MaterialApp

import 'package:flutter/material.dart';

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

/*
- title : 在任务管理窗口中所显示的应用名字
- theme : 应用各种 UI 所使用的主题颜色
- color : 应用的主要颜色值(primary color),也就是安卓任务管理窗口中所显示的应用颜色
- home : 应用默认所显示的界面 Widget
- routes : 应用的顶级导航表格,这个是多页面应用用来控制页面跳转的,类似于网页的网址
- initialRoute :第一个显示的路由名字,默认值为 Window.defaultRouteName
- onGenerateRoute : 生成路由的回调函数,当导航的命名路由的时候,会使用这个来生成界面
- onLocaleChanged : 当系统修改语言的时候,会触发å这个回调
- navigatorObservers : 应用 Navigator 的监听器
- debugShowMaterialGrid : 是否显示 Material design 基础布局网格,用来调试 UI 的工具
- showPerformanceOverlay : 显示性能标签
- checkerboardRasterCacheImages 、showSemanticsDebugger、debugShowCheckedModeBanner 各种调试开关
*/

class MaterialAppDemo extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      //debugShowMaterialGrid: true,
      showPerformanceOverlay: true,
      title: '应用名称',
      color: Colors.green,
      home: DemoPage(),
      theme: ThemeData(
        primaryColor: Colors.redAccent,
      ),
//      initialRoute: '/second',
//      routes: <String,WidgetBuilder>{
//        '/':(BuildContext context) => FirstScreen(),
//        '/second': (BuildContext context) => SecondScreen(),
//      },
    );
  }

}


class DemoPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new DemoPageState();
  }
}

class DemoPageState extends State<DemoPage> {

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 400.0,
      //滚动页面
      child: PageView(
        //翻滚方向
        scrollDirection: Axis.vertical,
        children: <Widget>[
          Container(
            color: Colors.redAccent,
            child: Center(
              child: Text('这是第一页',style: TextStyle(color: Colors.white,fontSize: 28.0),),
            ),
          ),
          Container(
            color: Colors.blue,
            child: Center(
              child: Text('这是第二页',style: TextStyle(color: Colors.white,fontSize: 28.0),),
            ),
          ),
          Container(
            color: Colors.orange,
            child: Center(
              child: Text('这是第三页',style: TextStyle(color: Colors.white,fontSize: 28.0),),
            ),
          ),
        ],
      ),
    );
  }
}



class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('First Screen'),
      ),
      body: new Center(
        child: new RaisedButton(
          child: new Text('First Screen'),
          onPressed: (){

          },
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Second Screen'),
      ),
      body: new Center(
        child: new RaisedButton(
          child: new Text('Second Screen'),
          onPressed: (){

          },
        ),
      ),
    );
  }
}