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<StatefulWidget> createState() {
    return DemoState();
  }
}

class DemoState extends State<DemoStatefulWidget>{
  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属性,设置之后,滑动时,标签将展示在进度条上;
效果如下:

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: <Widget>[
          Container(
              margin: EdgeInsets.fromLTRB(0, 10, 15, 0),
              child:
              Text('Radio:')),
          Row(
            children: <Widget>[
              Text('1'),
              Radio(
                value: '1',
                groupValue: this.radioSelectedPosition,
                onChanged: (radioChange) {
                  setState(() {
                    this.radioSelectedPosition = radioChange;
                  });
                  print('radioChange1: ${radioChange}'); //打日志到控制台)

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

效果:


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,水平有限,如发现问题,欢迎斧正!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容