Git口袋工具2 - Flutter基础知识
·
详细标注文档: 点击查看文档
页面主组件
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp( // 应用程序根组件
home: Scaffold( // 一种布局框架组件,实现多种效果的集合,可以选择性使用它的特性
appBar: AppBar(
centerTitle: true,
backgroundColor: Color.fromARGB(255, 147, 177, 233),
title: Text(
'这是一个flutter Demo',
textDirection: TextDirection.rtl,
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w800, color: Colors.blue),
),
),
body: Normallifecycle()),
));
}
有状态组件
快捷键:stf +Tab
使用场景:数据驱动视图的场景,数据发生改变就使用有状态组件
编写示例如下:固定模板
在状态组件的母组件写变量并进行required能进行父传子并实时更新UI
class IAmStateFull extends StatefulWidget {
const IAmStateFull({required xxx, super.key}); // 通过构造函数传毒数据 required表示参数必传
final xxx = 1; // 定义父传子的参数
@override
State<IAmStateFull> createState() => _IAmStateFullState();
}
class _IAmStateFullState extends State<IAmStateFull> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
无状态组件
快捷键:stl+Tab
适合数据一次性渲染,没有变量变化的情况
class IAmStateless extends StatelessWidget {
const IAmStateless({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [const Text('我是一个无状态组件')],
),
);
}
}
class 类的介绍
- 最简单普通类
- new的时候无需传入参数
- Dart class中未显式声明任何构造函数时,会自动生成「隐式无参默认构造函数」;
// 第一种:普通类无需参数初始化
class NormalClass {
NormalClass(); // 无参数构造函数 如果不写,默认会生成一个无参数的构造函数。
static const String normalClass = ‘NormalClass’;
} - 需要参数传入的普通类
- 传入参数是为了new的时候初始化类里面的值
- 下面函数中的AbstraClass(string xxx)就是这个类的构造函数
tips:如果之前学过js或者ts可以区别一下 js ts 构造函数是 constuctor
// 1.外界初始化class标注写法
class AbstractClass {
String inputValue = 'InputValue'; // 给变量初始值
AbstractClass(String xxxx) // 从外界传入初始值给InputValue
{
inputValue = xxxx;
}
/// 获取输入的值
getInputValue() {
return inputValue;
}
}
- 传入参数初始化class语法糖写法(tips:语法糖,可以理解为为了便捷开发而定义的一种替代语法)
1. 这里的语法糖是this
2. 构造函数使用this就可以不用进行手动赋值 注意对比上面的普通写法
tips:初学大部分情况下构造函数参数名和示例变量名相同就可以使用this,但是如果构造函数参数包含计算逻辑就不能使用。
// class外界初始化语法糖写法
class AbstractClass2 {
String inputValue = 'InputValue'; // 给变量初始值
AbstractClass2(this.inputValue); // this.写法是语法糖,其实就是简写
/// 一个类的方法-获取输入的值
getInputValue() {
return inputValue;
}
}
- 工具类创建方法
- 需要实现外界不能新new
- 只能向外提供方法及数据
- 构造函数中使用----> _
1. flutter中使用_表示的是私有的意思
// 第三种:工具类
// 1. 工具类不需要实例化,所以构造函数使用了._ 的方式来定义,确保只能在类内部调用。
// 2. 工具类里面的方法都是静态方法,所以可以直接通过类名调用,不需要实例化。
class ToolClass {
ToolClass._(); // 私有构造函数,防止外部实例化
static const String toolClass = 'ToolClass';
}
/// 使用方法 因为使用了static 无需实例化即可拿到值
final toolxxx = ToolClass.toolClass;
Tab组件的使用
main.dart 应用主界面
知识点:
1. 如何定义初始化数据
2. 如何传递数据给Tab组件
import 'package:flutter/material.dart';
import 'package:flutter_basic_comp/comment/component/tab_custom_view.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '方天画戟的Flutter 组件 Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Comp Code 组件 Demo'),
);
}
}
// 页面主组件
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 定义tab数据
final List<ITabsListItem> _tabsList = [
ITabsListItem('首页', Icons.home, '首页界面', color: Colors.blue),
ITabsListItem('发现', Icons.find_replace_sharp, '发现界面', color: Colors.purple),
ITabsListItem('消息', Icons.message, '消息界面'),
ITabsListItem('我的', Icons.account_balance, '我的界面欢迎 方天画戟'),
]; // 定义数据
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Column(
children: [
Container(
padding: const EdgeInsets.all(20),
child: const Text(
'点击下面tab进行组件测试',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
// Tab组件区域 Expanded 填充主轴剩余空间
Expanded(
child: TabCustomView(
tabs: _tabsList,
),
),
],
));
}
}
Tab组件
知识点:
- ✅✅数据传递-父传子
- ✅tab组件及控制器的绑定及使用
- ✅✅有状态组件如何获取父组件传递过来的数据
- ✅组件拆分
- 如何定义接口,通过class构造函数给class设置初始值方法
import 'package:flutter/material.dart';
/// Tab主组件
class TabCustomView extends StatefulWidget {
final List<ITabsListItem> tabs; // 定义父传子·接口
final Color? selectColor;
final String? fontSize;
final String? tabHeight;
const TabCustomView(
{super.key,
required this.tabs, // 添加required表示会父组件必传递的
this.fontSize,
this.tabHeight,
this.selectColor});
@override
State<TabCustomView> createState() => _TabCustomViewState();
}
class _TabCustomViewState extends State<TabCustomView>
with SingleTickerProviderStateMixin {
// 需要带上动画控制
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController =
TabController(length: widget.tabs.length, vsync: this); // 初始化tab控制器
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
} // 销毁时候需要销毁控制器
@override
Widget build(BuildContext context) {
return SizedBox(
height: double.infinity, // 占比100%
child: Column(
children: [
SizedBox(
// 盒子
width: double.infinity,
child: TabBar(
splashFactory: NoSplash.splashFactory, // 取消tabs点击切换波纹效果
controller: _tabController, // 需要绑定控制器
indicatorColor: Theme.of(context).primaryColor,
tabs: widget.tabs.map((e) => TabIcon(item: e)).toList()),
),
Divider(height: 1),
Expanded(
child: TabBarView(
controller: _tabController,
children:
widget.tabs.map((e) => TabsContent(item: e)).toList()))
],
));
}
}
/// tabItem项组件
class TabIcon extends StatelessWidget {
final ITabsListItem item;
const TabIcon({super.key, required this.item});
@override
Widget build(BuildContext context) {
return SizedBox(
child: Column(
spacing: 6,
children: [Icon(item.icon), Text(item.title)],
),
);
}
}
/// tabContent项组件(就是下面的组件)
class TabsContent extends StatelessWidget {
final ITabsListItem item;
const TabsContent({super.key, required this.item}); // 定义给父组件进行传输数据
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
width: double.infinity,
color: item.color,
padding: EdgeInsets.only(top: 20), // 设置顶部内边距为20
child: Column(
children: [
Icon(
item.icon,
size: 50, // 图标大小 不用width进行设置
),
Text(
item.title,
style: TextStyle(fontSize: 40, fontWeight: FontWeight.w800),
),
Text(
item.content,
style: TextStyle(fontSize: 40, fontWeight: FontWeight.w400),
),
],
));
}
}
/// tabsList接口
class ITabsListItem {
late String title;
late IconData icon;
late String content;
late Color? color;
ITabsListItem(String title, IconData icon, String content,
{Color? color = const Color.fromARGB(255, 59, 202, 202)}) {
// 定义接口并,部分参数设置可选值并进行初始化赋值 赋初始值参数需要加上花括号
this.title = title;
this.icon = icon;
this.content = content;
this.color = color;
}
}
// 1. Expanded组件,占满主轴剩余空间
// 2. SizedBox组件,设置固定宽高
// 3. Container组件.设置宽高及背景颜色等
规整页面代码,删除调试代码
import 'package:flutter/material.dart';
import 'package:flutter_basic_comp/comment/component/tab_custom_view.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '方天画戟的Flutter 组件 Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Comp Code 组件 Demo'),
);
}
}
// 页面主组件
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 定义tab数据
final List<ITabsListItem> _tabsList = [
ITabsListItem('首页', Icons.home, '首页界面', color: Colors.blue),
ITabsListItem('发现', Icons.find_replace_sharp, '发现界面', color: Colors.purple),
ITabsListItem('消息', Icons.message, '消息界面'),
ITabsListItem('我的', Icons.account_balance, '我的界面欢迎 方天画戟'),
]; // 定义数据
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: Column(
children: [
// Tab组件区域 Expanded 填充主轴剩余空间
Expanded(
child: TabCustomView(
tabs: _tabsList,
),
),
],
));
}
}
TabCustomview
知识点:
- 通过排列顺序调整页面结构
- 如何设置tab选中颜色
- column组件 能够竖直排列组件
- expand默认占满主轴空间
tips: - ?? 空值合并 如果前面一个为null or undefine 就用?? 后面的值
import ‘package:flutter/material.dart’;
/// Tab主组件
class TabCustomView extends StatefulWidget {
final List<ITabsListItem> tabs;
final Color? selectColor;
final String? fontSize;
final String? tabHeight;
const TabCustomView(
{super.key,
required this.tabs,
this.fontSize,
this.tabHeight,
this.selectColor});
@override
State<TabCustomView> createState() => _TabCustomViewState();
}
class _TabCustomViewState extends State<TabCustomView>
with SingleTickerProviderStateMixin {
// 需要带上动画控制
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController =
TabController(length: widget.tabs.length, vsync: this); // 初始化tab控制器
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: double.infinity, // 占比100%
child: Column(
children: [
// 设置内容区域 Expanded 填充主轴剩余空间
Expanded(
child: TabBarView(
controller: _tabController,
children:
widget.tabs.map((e) => TabsContent(item: e)).toList())), // 通过循环便捷创建组件
Container(
width: double.infinity,
padding: EdgeInsets.only(
top: 10), // 设置padding(内边距) all是全部设置,only是在某几个方向设置
child: TabBar(
splashFactory: NoSplash.splashFactory, // 取消tabs点击切换波纹效果
labelColor: widget.selectColor ?? Colors.blue, // 设置选中颜色
controller: _tabController, // 需要绑定控制器
indicatorColor: Colors.transparent, // 设置tab下面的指示条,可以改一改试一试
tabs: widget.tabs.map((e) => TabIcon(item: e)).toList()),
),
],
));
}
}
/// tabItem项组件
class TabIcon extends StatelessWidget {
final ITabsListItem item;
const TabIcon({super.key, required this.item});
@override
Widget build(BuildContext context) {
return SizedBox(
child: Column(
spacing: 6,
children: [Icon(item.icon), Text(item.title)],
),
);
}
}
/// TabContent项组件(就是下面的组件)
class TabsContent extends StatelessWidget {
final ITabsListItem item;
const TabsContent({super.key, required this.item}); // 定义给父组件进行传输数据
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
width: double.infinity,
color: item.color,
padding: EdgeInsets.only(top: 100), // 设置顶部内边距为20
child: Column(
children: [
Icon(
item.icon,
size: 50, // 图标大小 不用width进行设置
),
Text(
item.title,
style: TextStyle(fontSize: 40, fontWeight: FontWeight.w800),
),
Text(
item.content,
style: TextStyle(fontSize: 40, fontWeight: FontWeight.w400),
),
],
));
}
}
/// tabsList接口
class ITabsListItem {
late String title;
late IconData icon;
late String content;
late Color? color;
ITabsListItem(String title, IconData icon, String content,
{Color? color = const Color.fromARGB(255, 59, 202, 202)}) {
// 定义接口并,部分参数设置可选值并进行初始化赋值 赋初始值参数需要加上花括号
this.title = title;
this.icon = icon;
this.content = content;
this.color = color;
}
}
// 1. Expanded组件,占满主轴剩余空间
// 2. SizedBox组件,设置固定宽高
// 3. Container组件.设置宽高及背景颜色等
TabCustomView再优化,组件知识点讲解
知识点:
有状态组件组成
- 由两个class组件,第一层继承StatefulWidget ,第二层class继承State
- 第一层:
- 可以通过构造函数进行传递数据
- 可以定义一些不可变的参数(不能被修改)
- 第二层:
- 变量再整个class的生命周期存在
- 不能有显著构造函数,因为State对象是Flutter框架创建的
- by the way Build方法里面创建变量
- 每次build方法被调用变量都会被重新创建
- 定义的变量只能再这个build方法里面被调用
- 适合场景为临时变量或者动态值
媒体查询安全区高度
- 什么是安全区:例如手机电量那一栏就是属于软件的安全区,软件要注意避让安全区以防内容被遮盖
- 如何查询安全区高度:通过Flutter的媒体查询进行,定义安全区变量要找build方法
- final saveArea = MediaQuery.of(context).padding;
-
- 顶部安全区域(刘海屏等)
- 底部安全区域(底部导航栏等)
- 左侧安全区域(左滑返回等)
- 右侧安全区域(右滑返回等)
基础组件
- Container:容器组件,能设置宽高背景色
- SizeBox:容器组件,只能设置宽高,只设置宽高情况下建议用
- Column:竖直方向排列组件,传入children数组能竖直顺序排列数组内的组件, btw 横向排列组件是Row
整体代码
import 'package:flutter/material.dart';
/// Tab主组件
class TabCustomView extends StatefulWidget {
// 1. ✅第一层class通过构造函数传递参数
// 2. 继承StatefulWidget
// 3. 可以在这里配置参数-不变的
// 4. 定义参数不可变(不可被修改)
final List<ITabsListItem> tabs;
final Color? selectColor;
final String? fontSize;
final String? tabHeight;
// 构造函数,接受传递的值
const TabCustomView(
{super.key,
required this.tabs,
this.fontSize,
this.tabHeight,
this.selectColor});
@override
State<TabCustomView> createState() => _TabCustomViewState();
}
class _TabCustomViewState extends State<TabCustomView>
with SingleTickerProviderStateMixin {
// 第二层class参数
// 1.变量在整个class生命周期存在
// 2.变量能被修改
// 第二层class通过widget.访问上面的StatefulWidget的参数
// 1.不能有显著的构造函数,因为State对象是Flutter框架创建的
// 需要带上动画控制
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController =
TabController(length: widget.tabs.length, vsync: this); // 初始化tab控制器
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// 1. 在build方法里面创建变量
// 2. 每次build方法调用都需要创建变量
// 3. 只能在这个build里面调用
// 4. 适合临时计算或动态值
// 通过媒体查询查询设备的安全区域(刘海屏等)
// 1. 顶部安全区域(刘海屏等)
// 2. 底部安全区域(底部导航栏等)
// 3. 左侧安全区域(左滑返回等)
// 4. 右侧安全区域(右滑返回等)
final saveArea = MediaQuery.of(context).padding;
return SizedBox(
height: double.infinity, // 占比100%
child: Column(
children: [
// 设置内容区域 Expanded 填充主轴剩余空间
Expanded(
child: TabBarView(
controller: _tabController,
children:
widget.tabs.map((e) => TabsContent(item: e)).toList())),
Container(
width: double.infinity,
padding: EdgeInsets.only(top: 10, bottom: saveArea.bottom - 10),
// 设置padding(内边距) all是全部设置,only是在某几个方向设置
// 底部安全区域-6 是为了适配底部导航栏
child: TabBar(
splashFactory: NoSplash.splashFactory, // 取消tabs点击切换波纹效果
labelColor: widget.selectColor ?? Colors.blue, // 设置选中颜色
dividerHeight: 0,
controller: _tabController, // 需要绑定控制器
indicatorColor: Colors.transparent, // 设置tab下面的指示条,可以改一改试一试
tabs: widget.tabs.map((e) => TabIcon(item: e)).toList()),
),
],
));
}
}
/// tabItem项组件
class TabIcon extends StatelessWidget {
final ITabsListItem item;
const TabIcon({super.key, required this.item});
@override
Widget build(BuildContext context) {
return SizedBox(
child: Column(
spacing: 6,
children: [Icon(item.icon), Text(item.title)],
),
);
}
}
/// TabContent项组件(就是下面的组件)
class TabsContent extends StatelessWidget {
final ITabsListItem item;
const TabsContent({super.key, required this.item}); // 定义给父组件进行传输数据
@override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
width: double.infinity,
color: item.color,
padding: EdgeInsets.only(top: 100), // 设置顶部内边距为20
child: Column(
children: [
Icon(
item.icon,
size: 50, // 图标大小 不用width进行设置
),
Text(
item.title,
style: TextStyle(fontSize: 40, fontWeight: FontWeight.w800),
),
Text(
item.content,
style: TextStyle(fontSize: 40, fontWeight: FontWeight.w400),
),
],
));
}
}
/// tabsList接口
class ITabsListItem {
late String title;
late IconData icon;
late String content;
late Color? color;
ITabsListItem(String title, IconData icon, String content,
{Color? color = const Color.fromARGB(255, 59, 202, 202)}) {
// 定义接口,部分参数设置可选值并进行初始化赋值 赋初始值参数需要加上花括号
this.title = title;
this.icon = icon;
this.content = content;
this.color = color;
}
}
// 1. Expanded组件,占满主轴剩余空间
// 2. SizedBox组件,设置固定宽高
// 3. Container组件.设置宽高及背景颜色等
更多推荐

所有评论(0)