本文主要介绍Flutter项目的简单界面构建,以及布局
一.创建新的Flutter工程
- 使用终端进行创建
不支持大写字母,可以加下划线flutter create 项目名
创建成功后,可以使用VSCode或者Android studio打开 - 工程内容
lib文件夹:存放编写的代码,main.dart即为启动入口 - 项目启动
打开iOS或者安卓模拟器, 在工具栏找到启动调试,点击进行启动
二、flutter项目编写
- flutter项目的几个特性
热重载 hot reload 、 热重启 hot restart
运行一个flutter项目有三种方式: 冷启动:(从0启动)、 热重载 (最主要是执行build方法,其他方法不受影响)、 热重启(重新运行整个项目)
使用热重载可以快速预览布局变化,但是只有build方法会重置 - 简单编写启动内容
导入头文件(package:flutter/material.dart), 然后调用runApp函数import 'package:flutter/material.dart'; main(List<String> args) { runApp(Text("Hello world", textDirection: TextDirection.ltr)); }
- 具体内容设置
textDirection 传入文字方向
style 设置样式,字体颜色等
Center 也是一个Widget,实现居中操作runApp(Center( child: Text("Hello world", textDirection: TextDirection.ltr, style: TextStyle(fontSize: 30, color: Colors.red))));
三、Material设计风格
- Widget 即组件
万物皆是Widget, 通过嵌套Widget来实现布局功能- 有状态的Widget:
StatefulWedget 在运行过程中有一些状态(data数据)需要改变 - 无状态的Widget:
StatelessWidget 内容是确定的,没有状态(data数据)的改变
- 有状态的Widget:
- 几种Widget
- MaterialApp 会自动添加某些默认配置,不需要手动进行设置,比如文字方向等
runApp(MaterialApp( home: Center( child: Text("Hello World", style: TextStyle(fontSize: 30, color: Colors.orange)))));
- Scaffold 脚手架 用于快速搭建页面 创建导航栏、Tabbar等
主要参数有 appBar(导航栏或者Tabbar),body(界面内容)
debugShowCheckedModeBanner 控制右上角debug标签的显示runApp(MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text( "第一个项目", style: TextStyle(fontSize: 20, color: Colors.white), )), body: Center( child: Text("Hello world", textDirection: TextDirection.ltr, style: TextStyle(fontSize: 30, color: Colors.red))))));
- 自定义Widget子类
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return Text("hello World"); } }
build方法: 在创建自定义Widget子类时,会执行它的build方法,返回一个希望渲染的Widget元素,例如上例所示的Text Widget
StatelessWidget没办法去主动执行build方法,当我们的数据发生改变的时候,build方法会被重新执行
- build方法在什么情况下会执行?
1)当对应的StatelessWidget第一次被插入到Widget树中时,即第一次创建时
2) 当对应的父Widget发生改变时,子Widget会被重新构建
3) 如果对应的Widget依赖inheritedWidget的一些数据,inheritedWidget数据发生改变时
将需要构造的Widget放到build方法中返回,然后直接调用编写的Widget子类,即可得到想要的界面```
main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text(
"第一个项目",
style: TextStyle(fontSize: 20, color: Colors.white),
)),
body: Center(
child: Text("Hello world",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 30, color: Colors.red)))));
}
}
- 代码拆分抽取
将各个Widget包装成一个个自定义Widget子类,再进行组合,完成代码的拆分重组
main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(debugShowCheckedModeBanner: false, home: HomePageView());
}
}
class HomePageView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"第一个项目",
style: TextStyle(fontSize: 20, color: Colors.white),
)),
body: ContentBody());
}
}
class ContentBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text("Hello world",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 30, color: Colors.orange)));
}
}
- 一行写入多个控件
横向写入多个控件 Row
竖向写入多个控件 Column
class ContentBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Text("111"),
Text("Hello world",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 30, color: Colors.orange))
]));
}
}
默认从每行的最左端开始布局,使用mainAxisAlignment参数可以改变行内的布局位置
- @immutable
- 使用@immutable 注解标明的类及其子类均为不可变类,其中的属性均不可变,使用final修饰,不可定义状态
Widget类使用@immutable标记,所有的Widget都不可以直接定义状态 - StatelessWidget即是不可更改的类,不可定义状态
- StatefulWidget内部有一个抽象方法createState,此方法返回一个State类
- 在自定义的State子类中通过重写build方法实现控件
- StatefulWidget内部不可直接定义状态,但是可以在自定义的State子类中可以定义状态
class ContentBody extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return ContentBodyState();
}
}
class _ContentBodyState extends State<ContentBody> {
var flag = true;
@override
Widget build(BuildContext context) {
// TODO: implement build
return Center(
child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Checkbox(
value: flag,
onChanged: (value) {
setState(() {
flag = value ?? false;
});
}),
Text("Hello world",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 30, color: Colors.orange))
]));
}
}
总结:
继承自StatefulWidget的类负责实现createState方法,返回一个State类
State类负责实现Build方法,以及状态的创建,来实现功能
另外需要注意的几点:
- 状态的改变需要在setState回调中进行,否则不生效
- State类一般使用下划线_开头,如_ContentBodyState,下划线开头的类在别的文件无法访问,保证安全,而继承自StatefulWidget的类不加下划线
问题1:上述示例中,ContentBody返回的State类一定要定义为ContentBody泛型吗?可以改成别的StatefulWidget类吗?
可以,但没必要。
语法上无问题,但是,定义成此泛型,才可以使用系统提供的一个widget属性来构建出桥梁,连通对应的StatefulWidget子类,所以一般会这么写
问题2:继承自StatefulWidget的类,具体的作用?
1). 生成返回State类
2). 可以接收父Widget传过来的数据
网友评论