一、页面功能(实现加减控制数字文本变化)
首先查看入口函数:
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中加载图片
在工程根目录下创建一个
images目录
,并将图片avatar.png拷贝到该目录。-
在
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也即"字体图标",它是将图标做成字体文件,然后通过指定不同的字符而显示不同的图片。
三、实现效果
加号为图片组件,减一为icon组件。点击加号,数字加1;点击-1,数字减少1。