Flutter基础控件篇[1]

前言

拖了好久终于开始看Flutter,为了加深印象巩固学习效果,现将每次学习的内容总结成笔记,巩固效果也方便以后查阅。同时,笔记相关的Demo项目已经上传到Github,这里是传送门,欢迎指正。

正文
Flutter相关文档

1.官方文档
2.Flutter中文网
3.官方Demo(Github地址)

基础控件目录

官方基础控件目录

常用基础控件

不管在哪个前端平台,常用的基础控件都一样,大致包括:文本、图片、按钮、输入框、进度条、单选框和复选框、开关切换(Switch)、提示窗、对话框;布局用的控件(Layout)基本包含:横向布局、纵向布局、格子布局、重叠布局、各类包含不同约束条件的特定布局(内外间距,靠边居中,相对位置等);然后是一些根据常用程度封装的控件包括:列表控件、滑动控件(横纵方向),下拉刷新,抽屉(Drawer)等。

然后在Flutter中,控件分为StatefulWidget和StatelessWidget(有状态控件和无状态控件),无状态控件是死的,不会动态更新,所以实际使用的时候大多数情况下都是封装自己的StatefulWidget,StatefulWidget的状态存储在对应的State类里面,需要更新的时候可以通过调用setState()方法来刷新页面。
StatefulWidget基本代码模板如下:

class DemoStatefulWidget extends StatefulWidget{
  @override
  State createState() {
    return DemoState();
  }
}

class DemoState extends State{
  var data;
  @override
  Widget build(BuildContext context) {
    return Text(data);
  }

  void onDataChanged(newData){
    setState(() {//刷新控件
      data = newData;
    });
  }
}

接下来,按照上面梳理出的常用控件,我们一个一个来看。

文本 Text

Text官方文档
没啥注意点,属性看文档基本都能看懂。
基本使用

Widget build(BuildContext context) {
    return new Text(
      "A text in container",
      style: new TextStyle(
          color: Color(0xFF0000CD), fontStyle: FontStyle.normal, fontSize: 15),
    );
  }
图片 Image

Image官方文档
也没啥注意点。
基本使用

Widget build(BuildContext context) {
    return Image.network(//图片来自网络
      imageUrl,
      width: 200.0,
      height: 150.0,
    );
//    Image.asset(name);//图片来自项目内的资源
//    Image.file(file);//图片来自文件
//    Image.memory(bytes);//图片来自内存
  }
按钮 RaisedButton FlatButton

这两个按钮除了风格不同以外没什么别的区别,只有个别属性彼此有区分。
RaisedButton官方文档
FlatButton官方文档

Widget build(BuildContext context) {
    return RaisedButton(
      elevation: 5,
      color: Color(0xff87CEFA),
      child: Text("Print"),
      onPressed: () {}
    );
  }
输入框 TextField

TextField官方文档
基本使用

Widget build(BuildContext context) {
    return TextField(
      maxLines: 5,
      style: TextStyle(color: Colors.black),
      controller: editController,
      obscureText: false,
      decoration: InputDecoration(
        border: OutlineInputBorder(),
        labelText: 'Text',
      )
    );
进度条 Slider

Slider官方文档
注意点:
dividions属性,比如设置dividions属性为4,进度条被分为四等分,滑动时进度会停留在等分点上;
label属性,设置之后,滑动时,标签将展示在进度条上;
效果如下:

Flutter基础控件篇[1]_第1张图片
Slider

代码:

Widget build(BuildContext context) {
    return Slider(
      label: 'slider',
      value: rating,
      divisions: 4,
      onChanged: (newValue) {
        setState(() {
          rating = newValue;
        });
        print('rating: ${rating}'); //打日志到控制台)
      },
    );
CheckBox

很简单没啥要注意的。
CheckBox官方文档

Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.fromLTRB(0.0, 10, 0, 10),
      margin: EdgeInsets.fromLTRB(0, 10, 15, 10),
      alignment: Alignment(-1, 0),
      //min和max为最小进度值和最大进度值,不设置的话默认为0到1
      child: Slider(
        inactiveColor: Colors.cyan[100],
        activeColor: Colors.cyan[400],
        min: 0,
        max: 2,
        label: 'slider',
        value: rating,
        onChanged: (newValue) {
          setState(() {
            rating = newValue;
          });
          print('rating1: ${rating}'); //打日志到控制台)
        },
      ),
    );
  }
Radio

Radio官方文档
这个看文档有点迷糊,而且这个使用和Android的不一样。
这里要注意的是value和groupValue两个属性,value是当这个Radio选中的时候更新到onChange方法里的值,groupValue是,当它的值和value的值相同时,这个Radio就是选中状态,否则就是非选中状态。所以一般使用时都是把groupValue的值设定为一个动态变量,然后在onChange方法里更新这个动态变量。
基本使用

Widget build(BuildContext context) {
    
    return Column(
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.start,
        //靠左
        verticalDirection: VerticalDirection.down,
        children: [
          Container(
              margin: EdgeInsets.fromLTRB(0, 10, 15, 0),
              child:
              Text('Radio:')),
          Row(
            children: [
              Text('1'),
              Radio(
                value: '1',
                groupValue: this.radioSelectedPosition,
                onChanged: (radioChange) {
                  setState(() {
                    this.radioSelectedPosition = radioChange;
                  });
                  print('radioChange1: ${radioChange}'); //打日志到控制台)

                },
              ),
            ],
          ),
          Row(
            children: [
              Text('2'),
              Radio(
                value:'2',
                groupValue: this.radioSelectedPosition,
                onChanged: (radioChange) {
                  setState(() {
                    this.radioSelectedPosition = radioChange;
                  });
                  print('radioChange2: ${radioChange}'); //打日志到控制台)
                },
              ),
            ],
          ),
          Row(
            children: [
              Text('3'),
              Radio(
                value: '3',
                groupValue: this.radioSelectedPosition,
                onChanged: (radioChange) {
                  setState(() {
                    this.radioSelectedPosition = radioChange;
                  });
                  print('radioChange3: ${radioChange}'); //打日志到控制台)
                },
              ),
            ],
          ),
        ]);
  }

效果:


Flutter基础控件篇[1]_第2张图片
Radio
Switch

Switch官方文档

Widget build(BuildContext context) {
    return Switch(
      activeColor: Colors.deepOrange[300],
      activeTrackColor: Colors.deepOrange[600],
      inactiveTrackColor: Colors.blue[300],
      inactiveThumbColor: Colors.blue[100],
      inactiveThumbImage: NetworkImage(imageUrl),
      value: switchOn,
      onChanged: (switchOn){
        setState(() {
          this.switchOn = switchOn;
          print('switchOn: ${switchOn}'); //打日志到控制台)
        });
      },
    );
  }
最后,有一个重要而且特别的属性

在看第一个控件的时候,我就注意到这个属性,key,排在第一位。简单看文档看不明白到底是做什么用的,然后往下看的时候我注意到每一个控件都有key这个属性,而且都是排在第一位。于是我去查看了官方文档,结果我的个乖乖,开头就是一个整整10分钟的讲解视频,由于视频是全英文的并且字幕翻译的并不好,我反复看了三遍,才大致摸清楚了key的含义和用法。
要理解这个key的使用必须要对Flutter的控件树刷新机制有简单的了解。Flutter在构建Widget树的时候,同时会构建一个Element树,这个Element树才是显示和刷新页面的时候真正起作用的东西,Widget里面只是存了一些控件的属性值而已。在刷新Element树的时候,Flutter会依次对比每个控件的改变状态,首先是检查type,如果两个控件是相同的类型,type就是一样的,然后是检查key,比如你交换了页面中两个Text的位置,改变了Widget树的结构,如果此时你对这个控件设置了key,它会检查出前后状态下控件的key不一样,会判定这里有修改,然后Flutter会去遍历和刷新Element树,将它调整到正确的交换后的状态,否则的话,由于两个Text的type是一样的,Flutter检查之后会认为Element树没有必要刷新,此时就会出现错误,你会发现你交换控件之后页面上两个文本没有丝毫改变,如果你不了解这个机制的话,这个错误会显得莫名其妙并且完全摸不着头脑。
然后,key还包括ValueKey、LocalKey、GlobleKey,各种场景下适合使用的类型不相同,详细可见官方文档。然后后来找到一篇文章,基本很详细的把官方视频要阐述的内容解释清楚了,好文传送门。

尾声

以上,第一部分暂时整理这么多,接下来空余时间再逐步梳理剩下的控件,预计整个常用控件的梳理大概要分3篇笔记。个人从零逐步学习Flutter,水平有限,如发现问题,欢迎斧正!

你可能感兴趣的:(Flutter基础控件篇[1])