在上一篇文章 Flutter:环境搭建、项目创建 中我们搭建好了环境,并使用命令flutter create 项目名称
创建了一个默认应用。下面来简单看一下该默认应用。
参考:
切换到项目下可以看到如下图:
.dart_tool
存放与项目相关的一些工具包信息,不要随便修改.idea
,Android Studio
是基于 IDEA
开发的,所以会有一个.idea
,是对当前项目的一些基本配置android
和 ios
对应安卓和苹果两个工程lib
后续我们进行flutter
开发,所有代码都放在该目录下。该目录下会有一个main.dart
,该文件作为整个flutter
项目的一个启动入口test
用于做测试linux
、macos
、web
、window
对应其他平台,毕竟Flutter
的目标是跨平台(目前好像还不太成熟,当前主要用于app开发).gitignore
这个就不说了,搞过开发的都知道是干嘛的.metadata
用来记录与版本有关的一些信息,不要修改.packages
、pubspec.lock
、pubspec.yaml
与使用第三方库有关README.md
这个也不过多介绍了实际开发中主要会用到 lib
和 pubspec.yaml
第一次启动项目
热更新和热重启
热更新主要更新build
方法里面的内容,热重启会重新启动项目。
导入包
import 'package:flutter/material.dart';
此行代码作用是导入了 Material UI 组件库。Material (opens new window)是一种标准的移动端和web端的视觉设计语言, Flutter 默认提供了一套丰富的 Material 风格的UI组件。
应用入口
void main() {
runApp(const MyApp());
}
runApp
函数,存在于 Material UI 组件库
从下图中可以看到runApp
函数需要一个Widget
类型的参数
在这里Widget
是一个抽象类,所以需要实例化它的子类 class MyApp extends StatelessWidget {}
非常推荐 看一下 Flutter案例分析这个教学视频,里面的老师说的很正确,不要死记硬背,可以通过查看源码的方式来知道需要哪些参数。(window是ctrl+鼠标可以查看对应类的源码)
void main() {
runApp(const Text("Hello Flutter",
textDirection: TextDirection.ltr, textAlign: TextAlign.center));
}
查看Text
类,可以知道需要一个必填参数,也就是文本。这里还需要一个可选参数textDirection
:文字排列方向。点开textDirection
可以看到 textDirection
需要一个枚举值
void main() {
runApp(const Center(
child: Text("Hello Flutter", textDirection: TextDirection.ltr,style:TextStyle(
color:Colors.blue,
fontSize:30
) ,),
));
}
垂直并且水平居中
void main() {
runApp(MaterialApp(
home: Scaffold(
// Scaffold是内置的脚手架,帮助我们快速的搭建页面
appBar: AppBar(
title: const Text("第一个 Flutter App"),
), //app顶部导航栏
body: const Center(
child: Text("Hello Flutter",
style: TextStyle(color: Colors.blue, fontSize: 30)),
),
)));
}
在flutter可以理解为万物皆是Widget
,可以通过嵌套Widget
来实现一些功能。一层层嵌套搞得有点晕,而且有些类的实例还要求用const
进行定义
效果图
为了解决嵌套问题,可以将代码抽离成一个个的Widget。
Widget分为有状态和无状态两种:
注: 所有的widget里都不能写状态
runApp
方法的参数就是一个Widget,可以将这一部分进行抽离
void main() {
runApp( const MyApp());
}
//抽离runApp的参数为一个widget
class MyApp extends StatelessWidget{
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// build告诉flutter我们的widget希望渲染什么
//build方法没办法主动执行,只有数据发生改变时才会执行
//返回一个Widget
return MaterialApp(
home: Scaffold(
// Scaffold是内置的脚手架,帮助我们快速的搭建页面
appBar: AppBar(
title: const Text("第一个 Flutter App"),
), //app顶部导航栏
body: const Center(
child: Text("Hello Flutter",
style: TextStyle(color: Colors.blue, fontSize: 30)),
),
))
}
}
此时main方法里只有一条语句,这时可以使用箭头函数简写
main() => runApp( const MyApp());
将YCHomePage
进行进一步抽取,最终代码
import 'package:flutter/material.dart';
//使用箭头函数简写
main() => runApp(const MyApp());
//抽离runApp的参数为一个widget
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// build告诉flutter我们的widget希望渲染什么
//build方法没办法主动执行,只有数据发生改变时才会执行
//返回一个Widget
return const MaterialApp(home: YCHomePage());
}
}
//首页
class YCHomePage extends StatelessWidget {
const YCHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
// Scaffold是内置的脚手架,帮助我们快速的搭建页面
appBar: AppBar(
title: const Text("第一个 Flutter App"),
), //app顶部导航栏
body: const YCContentBody());
}
}
//内容
class YCContentBody extends StatelessWidget {
const YCContentBody({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Center(
child: Text("加油!", style: TextStyle(color: Colors.blue, fontSize: 30)),
);
}
}
视频讲解见:Flutter 案例分析
在Flutter开发中,所有的widget都不能定义状态,因为widget是不变的。
但是StatelessWidget中有一个抽象方法createState
,通过实现该抽象方法来定义一个单独的类用来管理状态
import 'package:flutter/material.dart';
//使用箭头函数简写
main() => runApp(const MyApp());
//抽离runApp的参数为一个widget
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// build告诉flutter我们的widget希望渲染什么
//build方法没办法主动执行,只有数据发生改变时才会执行
//返回一个Widget
return const MaterialApp(home: YCHomePage());
}
}
//首页
class YCHomePage extends StatelessWidget {
const YCHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
// Scaffold是内置的脚手架,帮助我们快速的搭建页面
appBar: AppBar(
title: const Text("第一个 Flutter App"),
), //app顶部导航栏
body: const YCContentBody());
}
}
//内容
class YCContentBody extends StatefulWidget {
const YCContentBody({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() {
//单独定义一个类,用来管理状态
return YCContentState();
}
}
//状态维护类,点开State可以看到其对应的泛型是StatefulWidget,而YCContentBody继承自StatefulWidget
class YCContentState extends State<YCContentBody> {
var flag = true;
@override
Widget build(BuildContext context) {
return Center(
child: Row(
//设置x轴的对齐方式
mainAxisAlignment: MainAxisAlignment.center,
children: [
Checkbox(
value: flag,
onChanged: (value) {
//不能直接赋值,需要借助setState方法,setState方法是继承自State的,用来改变状态
setState(() {
flag = value ?? false; //判定value是否为null
});
},
),
const Text(
"同意协议",
style: TextStyle(fontSize: 20),
)
]));
}
}
哎,感觉对我这种初学者有亿点点难。