接上篇,我们新建一个Flutter Project:
flutter项目中有android、ios、lib等目录,可能刚开始有不少同学建完项目,就直奔android目录准备开发了,但其实,flutter的编程目录是在lib下的,所有编程文件后缀都为.dart,我们也可以把其看做安卓开发时.java以及java目录,可以更好的理解!
其中的pubspec.yaml这个文件很重要,类似于安卓开发时app目录下的build.gradle,我们在引用一些第三方的工具或插件时都要在该文件中声明,如下图:
引入后点击右上角的Pakage get,就可以获取该包,然后再项目中引入该包路径,就可以使用里面提供的方法了。
在新建的flutter项目的lib目录下,都会有一个mian.dart,这个就是程序的入口,里面提供的有示例,在我们着手开始写代码之前,还是 有必要去了解一下Flutter UI方面的一些知识。
- dart导入包跟java一样,用import关键字,当你输入import时,AS会自动提示很方便;
- 如java一样,dart同样用class声明类,extends继承类;
- java的精髓是万物皆对象,flutter的精髓是万物皆组件,所以你在开发flutter时会经常用到Widget;
- Widget可以理解为安卓中的View;
- 更多内容可以去官网学习
我们在布局一个界面的UI时经常要用到两个类:StatelessWidget和StatefulWidget:
StatelessWidget表示静态页面,就像我们常说的写死的,不会有改变的;而StatefulWidget是动态的,也就是UI会根据数据的改变做出动态响应的;我们看到主程序里面第一个组类就是StatelessWidget:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
build方法中返回的Widget 就像是该界面整个UI的一个最顶级的ViewGroup,像一个底板,然后里面的接下来的所有组件都会在这个group中一层套一层的布局;另外,这个结构看起来似曾相识啊:
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
区别就是,安卓中我们用xml布局,而Flutter中我们要用代码布局,UI中的所有组件我们都要用代码一个一个实现,是不是有种想放弃的感觉,哈哈!
MaterialApp就是Material风格的app了,做安卓开发的再熟悉不过了,里面的属性大家可以自行查看官网说明,重点说home这个属性:字面意思,家,就是这个界面的家,在home中也就需要我们根据UI设计去一点一点布局了;
home: MyHomePage(title: 'Flutter Demo Home Page'),
MyHomePage继承了StatefulWidget,说明这个界面是一个动态的;我们需要知道,安卓开发中,我们可以直接去操控view,改变view的属性,但Flutter中却不能,我们需要通过数据的改变去重绘UI,也就是我们只能改变数据,而不能直接操控组件,跟微信小程序开发是一样的道理;
而实现要实现动态界面,StatefulWidget和State两个类是紧紧相连的:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
),
body: Center(
));
}
}
MyHomePage 重写createState方法,返回State(_MyHomePageState ),接下来该界面所使用的变量,方法等都可以在_MyHomePageState 类中声明,改变UI则可以通过方法 setState:
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
而真正布局的开始,则是在_MyHomePageState 的Widget build(BuildContext context)方法中:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
),
body: Center(
));
}
Scaffold 实现了Material风格的布局及组件,仅从布局意义上讲,我们仍然可以把其理解为一个ViewGroup,主要属性说明:
- appBar:Material 的标题栏;
- body:UI主要内容(标题栏以下)
- floatingActionButton: 在 Material 中定义的一个功能按钮;
- persistentFooterButtons:固定在下方显示的按钮;
- drawer:侧边栏;
- bottomNavigationBar:底部导航栏;
- backgroundColor:背景颜色;
- resizeToAvoidBottomPadding: 控制界面内容 body是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被键盘盖住内容;
对于组件的声明我们可以前面加上new如: new Text(‘标题’),也可以不加如:Text(‘标题’),所以大家在看到不同项目中有的有new,有的没有时不要疑惑,没有任何区别;接下来,我们来了解一下常用的一些组件:
- 文本:Text;
- 输入框:TextField;
- 列表:ListView;
- divider:Divider;
- 边框:BoxDecoration;
- 包裹容器:Container;
- 水平布局容器:Row;
- 垂直布局容器:Column;
- 可伸缩布局容器:Flexible;
- 图片:Image;
等等…不在过多罗列,各种组件都有其对应的各种属性如:margin,padding,width,heigth等等;
下面我们来实现一个上面是内容,底部是输入框的这么一个界面:
class _MyHomePageState extends State<MyHomePage> {
TextEditingController _textController = new TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: new Column(children: <Widget>[
new Text("Hello World"),
new Divider(height: 1.0), //分界线
new TextField(
controller: _textController,
decoration: new InputDecoration.collapsed(hintText: '请输入消息'),
)
]));
}
}
先用最简单的实现,首先思考布局,上面是内容,下面是输入框,这类似于LinlearLayout的垂直布局,那么在flutter中我们可以用Column来实现,需要注意的是:Column和Row容器中可以有多个子Widget,也就相当于可以有多个子View,类似于LinearLayout,RelayLayout等,对应的属性是children,字面意思:孩子们,而像Container,Flexible等容器中只能有一个组件,类似于ScrollView,对应的属性是child,对比children意思一目了然,而Text,Image等组件跟安卓中想同,为最小View,他们中不能再有组件;
另外注意组件的书写方式:
child:组件(
属性:xx,
属性:xx,
),
children: <Widget>[
组件(
属性:xx,
child:组件(
属性:xx,
child:xx,
),
),
组件(
属性:xx,
属性:xx,
),
]
所有属性以及组件间用逗号“,”隔开,并注意属性及组件的层次递进;
输入框TextField实现时需要一个控制器TextEditingController,再类中声明一下即可,过后我们就可以用这个对象实现获取输入框中的内容,清空输入框的内容等一系列操作了;
运行程序,效果如下:
本篇讲述了flutrer项目结构,布局规则,及不同组件的作用及使用方法,大家对Flutter项目的开发有一个最基本的了解之后,下一篇将继续讲解如何实现一个Flutter版的聊天机器人。