https://cloud.tencent.com/developer/article/2019869https://www.wanandroid.com/blog/show/2268https://www.wanandroid.com/blog/show/2
Scaffold
https://juejin.cn/post/6986548296357675016 Scaffold是Flutter自带的用于快速开发的框架或者称之为“脚手架”。它实现了基本的Material Design布局结构。 Scaffold常用的几个重要属性有:
- appBar:显示在界面顶部的一个标题栏
- body:页面的主题内容
- bottomNavigationBar :页面的底部导航栏
- drawer:抽屉菜单控件
- floatingActionButton :浮动按钮
MaterialApp
可以使用ThemeData
改变项目整体的样式,暗黑和白天模式
class _AppRootPageState extends State<AppRootPage> {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter 脚手架',
//应用的主题
theme: ThemeData(
//主背景色
primaryColor: Colors.blue,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.lightBlueAccent),
useMaterial3: true,
),
//应用程序默认显示的页面
home: const IndexPage(),
//debug模式下不显示debug标签
debugShowCheckedModeBanner: false,
//国际化语言环境
localizationsDelegates: [],
//配置程序语言环境
locale: const Locale('zh', 'CN'),
);
}
}
AppBar
显示在APP的顶部的控件,对应Android早期的ActionBar和火来的AppBar AppBar由leading、bottom、title、actions、flexibleSpace组成 简单使用:
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.close),
onPressed: (){},
),
title: Text(widget.title),
centerTitle: true,
actions: [
IconButton(onPressed: (){}, icon:const Icon(Icons.message)),
IconButton(onPressed: (){}, icon:const Icon(Icons.more_horiz_sharp)),
],
),
实现滑动的切换标签栏
import 'package:flutter/material.dart';
class Slip extends StatefulWidget {
const Slip(String s, {Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _SlipState();
}
class _SlipState extends State<Slip> with SingleTickerProviderStateMixin {
//控制器
late TabController _tabController;
//tab集合
List<Tab> tabs = <Tab>[];
//主题页面集合
List<Widget>bodyList = [];
@override
void initState() {
super.initState();
//初始化tab
tabs = <Tab>[
const Tab(text: "新闻",),
const Tab(text: "娱乐",),
const Tab(text: "文化",),
const Tab(text: "科技",),
];
//创建主题页面
for (int i = 0; i < tabs.length; ++i) {
bodyList.add(Center(child: tabs[i],));
}
_tabController = TabController(length: tabs.length, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: TabBar(
tabs: tabs,
controller: _tabController,
isScrollable: true,
),
centerTitle: true,
),
body: TabBarView(
controller: _tabController,
children: bodyList,
),
);
}
}
文本及其样式
Text
**Text **
用于显示简单样式文本,类似原生控件中的**TextView**
Text的常见属性有:
- textAlign:对齐方式,可以指定是左对齐,右对齐,还是居中
- maxLines:指定文本的最大行数,可以搭配overflow指定超出部分的截断方式,默认是直接截断不显示
- style:指定文本的样式,可以指定大小,风格,颜色等
TextStyle
对应Text中的style属性,用于指定文本显示的样式如颜色、字体、粗细、背景等
TextSpan
可以指定一个文本内容的不同部分按照不同的样式显示
const TextSpan({
TextStyle style,
String text,
List<TextSpan> children,
GestureRecognizer recognizer,
});
其中style 和 text属性代表该文本片段的样式和内容。 children是一个TextSpan的数组,也就是说TextSpan可以包括其他TextSpan。而recognizer用于对该文本片段上用于手势进行识别处理。下面我们看一个效果(图3-4),然后用TextSpan实现它。
Text.rich(TextSpan(
children: [
TextSpan(
text: "Home: "
),
TextSpan(
text: "https://flutterchina.club",
style: TextStyle(
color: Colors.blue
),
recognizer: _tapRecognizer
),
]
))
- 上面代码中,我们通过 TextSpan 实现了一个基础文本片段和一个链接片段,然后通过Text.rich 方法将TextSpan 添加到 Text 中,之所以可以这样做,是因为 Text 其实就是 RichText 的一个包装,而RichText 是可以显示多种样式(富文本)的 widget。
- _tapRecognizer,它是点击链接后的一个处理器(代码已省略),关于手势识别的更多内容我们将在后面单独介绍。
Image
本地图片
本地图片的存放位置,并且需要在pub文件下配置,注意缩进。添加后重新运行项目才会加载静态资源,热更新检测不到新添加的静态资源 加载本地图片,并且正方形显示会拉伸
Image.asset()
网络图片
Image.network()
圆形图片
可以使用CircleAvater()来包裹我们的图片,为图片设置圆角
const CircleAvatar(backgroundImage: AssetImage("images/cat.jpg"),radius: 50,)
占位图
对于网络请求设置图片可以使用FadeInImage来设置请求失败时的占位图
FadeInImage(placeholder:"" image:"")
Button
ElevatedButton
漂浮按钮,它默认带有阴影。使用很简单
ElevatedButton(
child: Text("normal"),
onPressed: () {},
);
TextButton
文本按钮,默认背景透明不带阴影的按钮
OutlinedButton
OutlinedButton默认有一个边框,不带阴影且背景透明。
IconButton
IconButton是一个可点击的Icon,不包括文字,默认没有背景,点击后会出现背景,
FloatingActionButton
圆形浮动按钮
带图标的按钮
所有的按钮都有一个Icon构造函数,可以指定按钮的图标
ElevatedButton.icon(
icon: Icon(Icons.send),
label: Text("发送"),
onPressed: _onPressed,
),
OutlinedButton.icon(
icon: Icon(Icons.add),
label: Text("添加"),
onPressed: _onPressed,
),
TextButton.icon(
icon: Icon(Icons.info),
label: Text("详情"),
onPressed: _onPressed,
),
StatefulWidget和setState
有状态控件和设置状态 首先Home是一个有状态的控件,它的状态的监控通过_HomeState去监听 为什么要设计无状态和有状态的控件呢?
Color参数
Color.ragb0等 https://www.bilibili.com/video/BV138411B7Zz?p=12&spm_id_from=pageDriver&vd_source=2c2d0ce64b817501491ef975f77fea05
输入框
TextField控件
TextFiled类似Android原生中的EditView,用于输入文本
需要定义一个Controller接收输入框中的值 点击一下打印输入框上的内容 实现一个登录注册页面的输入框样式:
import 'package:flutter/material.dart';
class MyTextField extends StatefulWidget {
const MyTextField({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _TextFiledState();
}
class _TextFiledState extends State<MyTextField> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("输入框"),
),
body: Column(
children: [
TextField(
obscureText: true, //隐藏文本
maxLines: 1,
maxLength: 12,
decoration: InputDecoration(
// icon: Icon(Icons.people),
prefixIcon: Icon(Icons.people),
hintText: '请输入账号',
labelText: '请输入账号',
suffixIcon:
IconButton(onPressed: () {}, icon: const Icon(Icons.cancel)),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(30)),
),
),
)
],
),
);
}
}
TextEditingController
文本控制器
创建控制器
//文本控制器
TextEditingController _controller = TextEditingController();
通过控制器设置TextField初始值
_controller =
TextEditingController.fromValue(const TextEditingValue(text: '初始化内容'));
绑定控制器
TextField(
controller: _controller,
)
设置监听
void setTextController() {
//TextEditingValue发生变化时和获取失去焦点时都会调用
_controller.addListener(() {
text=_controller.text;
print(text);
});
}
class _TextFiledState extends State<MyTextField> {
//文本控制器
TextEditingController _controller = TextEditingController();
//输入框上的内容
String text = "";
@override
void initState() {
// TODO: implement initState
super.initState();
_controller =
TextEditingController.fromValue(const TextEditingValue(text: '初始化内容'));
setTextController();
}
void setTextController() {
//TextEditingValue发生变化时和获取失去焦点时都会调用
_controller.addListener(() {
text=_controller.text;
print(text);
});
}
···
}
点击收起键盘
在外层包裹一个手势即可
return GestureDetector(
onTap: (){
SystemChannels.textInput.invokeMethod('TextInput.hide');
},
child: Scaffold(
appBar: AppBar(
title: const Text("输入框"),
),
body: Column(
children: [
TextField(
controller: _controller,
// obscureText: true,
//隐藏文本
maxLines: 1,
maxLength: 12,
decoration: InputDecoration(
// icon: Icon(Icons.people),
prefixIcon: const Icon(Icons.people),
hintText: '请输入账号',
labelText: '请输入账号',
suffixIcon: IconButton(
onPressed: () {}, icon: const Icon(Icons.cancel)),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(30)),
),
),
)
],
),
),
);
}
SafeArea
SafeArea 是 Flutter 中的一个基础小部件,用于确保其子组件不会被系统视图(如状态栏、导航栏、刘海屏等)遮挡。它通过内部的 MediaQuery 和 ViewPadding 来获取屏幕的布局边界,并相应地调整其子组件的位置。
ListView
直接使用
Builder构建
itemCount:指定数据的数量 itemBuilder:构建每一个子项
separated带分割线的构造
带ListTitle的item
弹窗
对话弹窗
通过AlertDialog构造一个对话弹窗,返回值只能是AlertDialog 对话弹窗中的按钮通过actions属性构造 按钮中的点击取消通过Navigator.pop();实现事件
底部弹窗
showModelBottomSheet()构造底部弹窗 弹窗的返回值可以自定义
更复杂的实现