flutter笔记4:运用material原生控件开辟一个APP

接着上一篇,我们做一个如许的APP:
《flutter笔记4:运用material原生控件开辟一个APP》

最先之前,我发明了一个好玩的东西,每次我们在终端中输入敕令:

flutter run

终端里会有这个东西:
《flutter笔记4:运用material原生控件开辟一个APP》

根据上图所示,我们的进入这个网页看看是个啥:
《flutter笔记4:运用material原生控件开辟一个APP》

好嵬峨上的觉得,详细是干吗的,我也不晓得,有兴致的同砚能够点进去把玩把玩,今后搞邃晓了再更吧。

第一步

先建立一个列表。

回到main.dart中,把本来的代码悉数清空,复制以下代码:

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

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

class MyApp extends StatelessWidget {
  @override
  //构建一个容器
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Startup Name Generator',
      home: new RandomWords(),//定义子组件为有状况控件RandomWords类的实例
    );
  }
}

//定义有状况控件RandomWords类
class RandomWords extends StatefulWidget {
  @override
  createState() => new RandomWordsState();//建立有状况控件RandomWords的状况类实例:RandomWordsState
}

//定义状况类RandomWordsState
class RandomWordsState extends State<RandomWords> {
  @override
  final _suggestions = <WordPair>[];  //用于保留随机字符串词组,注重这是一个数组变量
  final _biggerFont = const TextStyle(fontSize: 18.0);   //用于标识字符串的款式

  //构建一个脚手架,内里塞入前面定义好的_buildSuggestions类
  Widget build(BuildContext context) {
    return new Scaffold (
      appBar: new AppBar(
        title: new Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(), 
    );
  }

  //定义一个子控件,这个控件就是安排随机字符串词组的列表
  Widget _buildSuggestions() {
    return new ListView.builder(  //ListView(列表视图)是material.dart中的基本控件
      padding: const EdgeInsets.all(16.0),  //padding(内边距)是ListView的属性,设置其属性值
      //经由过程ListView自带的函数itemBuilder,向ListView中塞入行,变量 i 是从0最先计数的行号
      //此函数会自动轮回并计数,咋完毕的我也不晓得,走着瞧咯
      itemBuilder: (context, i) {
        if (i.isOdd) return new Divider();//奇数行塞入分割线对象
        final index = i ~/ 2;  //当前行号除以2取整,获得的值就是_suggestions数组项索引号
        // 假如盘算获得的数组项索引号超出了_suggestions数组的长度,那_suggestions就再生10个随机组合的字符串词组
        if (index >= _suggestions.length) {
          _suggestions.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_suggestions[index]);//把这个数据项塞入ListView中
      }
    );
  }

  //定义的_suggestions数组项属性
  Widget _buildRow(WordPair pair) {
    //ListTile和Text都是material.dart中的基本控件
    return new ListTile(
      title: new Text(
        pair.asPascalCase,  //运用驼峰款式
        style: _biggerFont,
      ),
    );
  }
    
}

看到这里,是不是是有点晕,种种声明、种种援用,另有回调,把上面的代码,用下面的图剖析下构造,看看究竟怎样个状况:
《flutter笔记4:运用material原生控件开辟一个APP》

能够发如今StatelessWidget和State类中都有一个Widget范例的函数build(),觉得有点像类的初始化要领construct(),而RandomWords对象为何只运用了createState()却没有build(),我也不晓得,走着瞧吧。当对象实例化的时刻,起首实行Widget build(BuildContext context){}函数,函数中BuildContext范例的参数context,到目前为止还不晓得干吗用的,临时疏忽其意义吧。

material范例的子控件都经由过程回调函数的体式格局建立,我读起来有些不习惯,但经由过程回调,免去了先声明再运用的贫苦,而且能够直接对对象的属性举行设置,经由过程build()一层层回调,代码简约不少,而代码中运用到的material内置控件,我就不逐一引见了,有兴致的同砚请参考material官方API,注重material控件索引在页面右侧的列表,别找到左侧去了。

注重,碰到这类声明类属性的花样:_[变量名]。按官方的意义是,假如变量名的前缀有_下划线,示意强迫转换为私有变量,相当于声明变量为private,但运用这个变量的时刻,照样要将下划线举行完整的誊写。

保留代码后运转一下,能够看到APP变成了这个模样:
《flutter笔记4:运用material原生控件开辟一个APP》

向下转动尝尝,发明能够一向滚下去~

第二步

向列表里加个_珍藏_标签按钮,使每行能够标记珍藏或作废珍藏。这个_珍藏_标签就是状况,既然要修正状况,一定要到state中举行啦。

到对象RandomWordsState中定义一个对象,用于存储标记。为何要零丁存储标记呢?因为如许就不须要往行对象(ListTile)中增加标记,降低了对象的复杂度。以下:

class RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];

  final _saved = new Set<WordPair>();  //新加这一句

  final _biggerFont = const TextStyle(fontSize: 18.0);
  ...
}

为何存储标记的是对象而不是一个数组呢?大概是想趁便教我们运用一下Set对象吧,听说Set对象不允许有重复的项目,轻易背面模仿客栈的结果,异常合适这类场景。然后我们到每一个行增加一个标记珍藏的控件:

Widget _buildRow(WordPair pair) {
    //定义一个布尔变量,用于判断行控件ListTile是不是被标记为珍藏
    final alreadySaved = _saved.contains(pair);
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      //安置图标控件
      trailing: new Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      //定义点击事宜,控制图标的款式的切换
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
    },
    );
  }

注重,在onTap事宜中,运用到了setState()要领(用过vue或react的玩家是不是是很熟悉呀),在这个要领里修正变量值,即可触发state对象实行build()要领重绘对象。这里每次变动对象_saved后,都邑重绘ListTile对象,而静态变量alreadySaved也被从新定义,因而不必忧郁alreadySaved值不被更新的题目,假如去除final关键字,Dart语法会报错,还请途经大神点拨一下缘由。

保留代码后,能够看到APP革新了,每一行都增加了一个心型图标,重复戳这个行,还自动配有动画结果:
《flutter笔记4:运用material原生控件开辟一个APP》

第三步

到场一个导航栏款式的客栈。

先往主页面控件(AppBar)中增加一个能够进入珍藏列表的进口:

class RandomWordsState extends State<RandomWords> {
  ...
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Startup Name Generator'),
        //为AppBar对象的actions属性增加一个IconButton对象,actions属性值能够是Widget范例的数组
        actions: <Widget>[
          new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved), 
          //能够尝尝增加这两行后APP上有什么结果
          new IconButton(icon: new Icon(Icons.add), onPressed: _pushSaved), 
          new IconButton(icon: new Icon(Icons.create), onPressed: _pushSaved), 
        ],
      ),
      body: _buildSuggestions(),
    );
  }
  ...
}

因为没有定义_pushSaved函数,直接复制上面解释申明的代码会报错,因而,定义一个void范例的函数_pushSaved:

class RandomWordsState extends State<RandomWords> {
  ...
  void _pushSaved() {
  }
}

这时刻能够看到右上角多了3个图标,如图:

《flutter笔记4:运用material原生控件开辟一个APP》

然后我们往_pushSaved()函数中增加代码,让珍藏夹玩起来:

void _pushSaved() {
    //建立导航栏控件Navigator,然后往内里塞入MaterialPageRoute控件
    Navigator.of(context).push(
      new MaterialPageRoute(
        builder: (context) {
          //经由过程遍历_saved对象,猎取已珍藏的行对象
          final tiles = _saved.map(
                (pair) {
              return new ListTile(
                title: new Text(
                  pair.asPascalCase,
                  style: _biggerFont,
                ),
              );
            },
          );
          //函数的的链式挪用,猎取到增加好分割线的ListTile控件
          final divided = ListTile
              .divideTiles(            //divideTiles()函数,向每一个tile距离插进去一个1像素宽的边框
                context: context, 
                tiles: tiles,
              )
              .toList();  //不要遗漏这个函数,不然进入珍藏夹直接崩溃
          return new Scaffold(
            appBar: new AppBar(
              title: new Text('珍藏的列表项目'),
            ),
            body: new ListView(children: divided),  //直接将准备好的ListTile塞入个中,完成内容添补
          );
        },
      ),
    );
  }

保留代码后,革新APP,如图:
《flutter笔记4:运用material原生控件开辟一个APP》

如上图所示,赤色的箭头示意点击按钮后页面的切换,绿色箭头示意珍藏夹的值的对比,有无发明我们并没有写返回主页按钮的代码,这个返回按钮从哪来的呢?是由Navigator对象自动天生的,而且自动指向到主页面的路由,不过遗憾的是,没有到场返回手势的支撑,若有须要,还得自身写,详细怎样写,随着我的笔记走吧,我如今也不晓得。

人人注重看主页列表和珍藏夹列表的区分,二者都是列表,都是运用的ListView和ListTile对象,但完成的体式格局完整差别,插进去行对象和分割线的差别很有意义,有兴致的同砚能够自行修正下代码,看看能不能将两种列表的构建要领对换一下,参考官方材料ListViewListTile

第四步

变动UI主题作风。

这一步超等简朴,往MaterialApp对象里增加theme属性值即可:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Startup Name Generator',
      //增加theme属性值,塞入ThemeData对象
      theme: new ThemeData(
        primaryColor: Colors.white,
      ),
      home: new RandomWords(),
    );
  }
}

再保留,革新APP尝尝,主题变成了白色作风:

《flutter笔记4:运用material原生控件开辟一个APP》

ThemeData()要领自身供应了许多配色计划,玩家能够参考ThemeData官方申明,控制其壮大功用。没想到变动主题云云轻松,在当前APP界愈来愈寻求视觉体验晋级的趋向下,运用flutter开辟APP的玩家应当欣喜不少吧~

好勒,此次官方萌新课程的搬运就到这里,我是真的超喜好这个萌新课程,连课程总结都帮我写好了:

  • 从头最先建立一个Flutter运用程序。
  • 誊写了Dart言语的代码。
  • 学会了挪用外部的第三方库。
  • 体验热更新带来的开辟周期加快。
  • 学会运用有状况控件,增强了运用的交互。
  • 运用ListView和ListTiles建立了一个支撑懒加载的无穷转动列表。
  • 建立了一组路由并完成了主路由和新路由之间的跳转逻辑。
  • 相识怎样运用主题变动运用UI的表面。

自我总结一下,flutter是一个控件高度集成化的开辟平台,控件的完整度极高,控件之间的交互完成也倾向于傻瓜化,比方自动天生返回按钮、主题作风全局可控。只需把握好状况值和控件之间的嵌套关联,开辟者险些不须要零丁敲代码完成跳转逻辑,代码几乎不要太简约,不知不觉间就写好了一个APP。而VScode中的Dart Code插件也实在太好用,代码提醒、函数用法和参数都有详实的申明,看得出谷歌拿出了实足的诚意要在跨平台开辟上面大搞特搞一番。

《flutter笔记4:运用material原生控件开辟一个APP》

固然了,满屏幕的回调函数让我这类编程头脑还停留在C言语时期的菜鸟来讲,扶墙~ 头有点晕,还须要点时候逐步顺应一下下,也因为我没有那末深挚的手艺功底,对这个教程的明白还比较有限,可能有写的不对或不好的处所,也迎接人人斧正,特别我花了一天一夜写了这篇稿也是蛮不容易了,有途经的高手不说两句也是哪啥了是吧。固然,我有空的时刻抓紧读一读Dart 语法基本官方原版,有了新的发明也会写稿分享出来。

好啦就写到这里,广告时候,对flutter感兴致的小伙伴能够关注我,迎接人人到Flutter圈子中投稿,也能够联络管理员到场我们的flutter微信群嗨聊,感谢恭维~!
flutter 中文社区(官方QQ群:338252156)

    原文作者:燃烧的鱼丸
    原文地址: https://segmentfault.com/a/1190000013672695
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞