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。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容