Flutter入门(二)——实现一个简单的demo页面

一、页面功能(实现加减控制数字文本变化)

首先查看入口函数:

import 'package:flutter/material.dart';
/*
* 入口函数
* */
void main() {
 runApp(MyApp());
 //跟下面写法效果一致
//main(){
//  return new MyApp();
//}
}

类MyApp:

/*
* 这里相当于Android中的Application类
* StatelessWidget表示无状态控件
* */

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    /*
    * MaterialApp表明app的风格是Material Design风格的
    * 这里我们可以配置app的主题相关属性比如颜色,按钮风格等等,类似于Android中的style文件
    * */
    return MaterialApp(
      title: 'Flutter Demo',
      /*主题相关配置
      * 这里我们可以配合app整体的主题样式,比如整体颜色,控件默认的样式等
      * */
      theme: ThemeData(
        /*这个地方就类似于Android中的style文件配置,主要就是主题的配置*/
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      /*home指定了启动后显示的页面
      * 类似于我们在AndroidManifest中配置启动页面
      * */
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

MyHomePage:

/*
* StatefulWidget是一个有状态的控件,如果你的页面需要更新ui,那么该页面就要继承自StatefulWidget
* 如果只是一个纯展示的页面,只需要继承自StatelessWidget即可
* MyHomePage在上面已经被指定为启动页面
* 该页面有一个计数的逻辑,会更新ui,所以需要继承自StatefulWidget
* */
class MyHomePage extends StatefulWidget {
  /*Dart 中的构造方法  {}里面的参数表示可选参数,跟kotlin概念差不多
  * this.title默认会把值赋给下面的title
  * */
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".
  /*声明一个变量 用final修饰表示只能赋一次值
  * 在上面的构造上方法中已经有赋值操作了,所以后面我们就不能再更改title的值了
  * */
  final String title;
/*所有继承自StatefulWidget的控件都要重写createState()这个方法
  * 可以理解为指定该页面的状态是由谁来控制的
  * 在Dart中下划线开头声明的变量和方法,其默认访问权限就是私有的
  * 类似于java中用private关键字修饰,只能在类的内部访问
  * */
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

state:

/*
*State是一个状态对象,<>里面是表示该状态是跟谁绑定的。
* 我们修改状态时就是在该类中进行编写
*
* */
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      //调用这个setState方法是告诉flutter框架当前状态中某些情况发生了改变,会导致重新运行下面的build
      //方法,所以此视图可以反映更新的值。如果我们没有调用setState改变了_counter变量,那么build方法就不会被调用
      //结果导致没有任何变化发生
      _counter++;
    });
  }
  void _reduceCounter(){
    setState(() {
      _counter--;
    });
  }

build:

 @override
  Widget build(BuildContext context) {
    //每当setState方法被调用的时候就会重新调用这个方法,例如上面的_incrementCounter所做的
    //flutter框架已经做了一点优化,让重新运行的build方法执行的更快,这样的话你可以rebuild 需要更新的任何事情
    //而不需要单独改变每一个widgets的用例

/*Scaffold可以看作是Material Design中的一个模板
*看源码发现它继承自StatefulWidget,包含了appBar,body,drawer等控件
* */
    return Scaffold(
      /*appBar相当于Android中的ToolBar*/
      appBar: AppBar(
        /*这里的widget实际上就是MyHomePage*/
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      /*中间的内容布局*/
      body: Center(
        //Center是一个布局widget. It takes a single child and positions it
        // in the middle of the parent.
        /*Column表示一行 对应的Row表示一列*/
        child: Column(
          /*mainAxisAlignment翻译成中文就是主轴对准的意思,我们可以把值设置为start,end等等*/
          mainAxisAlignment: MainAxisAlignment.center,
          /*子控件,是一个List类型*/
          children: <Widget>[
            /*文本控件
               这里我们可以修改样式
              style: TextStyle(fontSize: 30,letterSpacing: 3)
            * */
            Text(
              '你点击的次数:',
                style: TextStyle(fontSize: 30,letterSpacing: 3),
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            /*我们新增一个按钮,用来实现点击使计数器减一*/
            RaisedButton(
              /*_reduceCounter是上面我们自己新增的方法,Dart中可以把方法作为参数传递*/
              onPressed: _reduceCounter,
              child:
                  Icon(Icons.exposure_neg_1)
            )
          ],
        ),
      ),

      /*浮动按钮*/
      floatingActionButton: FloatingActionButton(
        /*_incrementCounter实际上就是一个上面默认的_incrementCounter()方法*/
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Image.asset("images/add.png",
          width: 100.0,
        ),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

二、补充说明

此demo页面涉及到两个组件:图片和icon。在这里做一个简单的介绍,更详细的学习请参考flutter官网和相关书籍

1. 图片

在flutter中,我们可以通过Image组件来加载并显示图片,Image的数据源可以是asset、文件、内存以及网络。

ImageProvider

ImageProvider 是一个抽象类,主要定义了图片数据获取的接口load(),从不同的数据源获取图片需要实现不同的ImageProvider ,如AssetImage是实现了从Asset中加载图片的ImageProvider,而NetworkImage实现了从网络加载图片的ImageProvider。

从asset中加载图片
  1. 在工程根目录下创建一个images目录,并将图片avatar.png拷贝到该目录。

  2. pubspec.yaml中的flutter部分添加如下内容:

      assets:
        - images/avatar.png
    

    注意: 由于 yaml 文件对缩进严格,所以必须严格按照每一层两个空格的方式进行缩进,此处assets前面应有两个空格。

    加载该图片

Image(
  image: AssetImage("images/avatar.png"),
  width: 100.0
);

​ Image也提供了一个快捷的构造函数Image.asset用于从asset中加载、显示图片:

Image.asset("images/avatar.png",
  width: 100.0,
)
从网络加载图片
Image(
  image: NetworkImage(
      "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4"),
  width: 100.0,
)

Image也提供了一个快捷的构造函数Image.network用于从网络加载、显示图片:

Image.network(
  "https://avatars2.githubusercontent.com/u/20411648?s=460&v=4",
  width: 100.0,
)
2. ICON

Flutter中,可以像web开发一样使用iconfont,iconfont也即"字体图标",它是将图标做成字体文件,然后通过指定不同的字符而显示不同的图片。

三、实现效果

image.png

加号为图片组件,减一为icon组件。点击加号,数字加1;点击-1,数字减少1。

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

推荐阅读更多精彩内容