【笔记】Flutter的Scaffold脚手架组件

前言

Flutter的Scaffold脚手架组件学习笔记

Scaffold组件

appBar:定义顶部导航栏
body:定义页面主体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("文本内容"),
),
body: const Center(
child: Text(
"文本内容",
textDirection: TextDirection.ltr,
),
),
),
));
}

BottomNavigationBar底部导航栏

lib/main.dart
1
2
3
4
5
6
7
8
9
10
11
import 'package:flutter/material.dart';
import './pages/tabs.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: const Tabs(),
),
));
}

iconSize:图标大小
fixedColor:选中的图标颜色
type: BottomNavigationBarType.fixed:可以放大于3个按钮
bottomNavigationBar:定义底部导航栏
currentIndex:定义当前选中按钮的索引
onTap:按钮被点击触发的事件
items:所有按钮元素

lib/pages/tabs.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import 'package:flutter/material.dart';
import './tabs/page_one.dart';
import './tabs/page_two.dart';

class Tabs extends StatefulWidget {
const Tabs({super.key});

@override
State<Tabs> createState() => _TabsState();
}

class _TabsState extends State<Tabs> {

int _currentIndex = 0;
final List<Widget> _pages = const [
PageOne(),
PageTwo(),
];

@override
Widget build(BuildContext context) {
return Scaffold(
body: _pages[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
iconSize: 20,
fixedColor: Colors.red,
type: BottomNavigationBarType.fixed,
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "PageOne",
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "PageTwo",
),
],
),
);
}
}
lib/pages/tabs/page_one.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import 'package:flutter/material.dart';

class PageOne extends StatefulWidget {
const PageOne({super.key});

@override
State<PageOne> createState() => _PageOneState();
}

class _PageOneState extends State<PageOne> {
@override
Widget build(BuildContext context) {
return const Text("PageOne");
}
}
lib/pages/tabs/page_two.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import 'package:flutter/material.dart';

class PageTwo extends StatefulWidget {
const PageTwo({super.key});

@override
State<PageTwo> createState() => _PageTwoState();
}

class _PageTwoState extends State<PageTwo> {
@override
Widget build(BuildContext context) {
return const Text("PageTwo");
}
}

实现中间凸起的底部导航栏

color:浮动按钮的底纹颜色
borderRadius:浮动按钮的底纹圆角
backgroundColor:浮动按钮的背景颜色
floatingActionButtonLocation:浮动按钮的位置

FloatingActionButtonLocation.centerDocked:Dock中间
FloatingActionButtonLocation.centerFloat:屏幕浮动中间
FloatingActionButtonLocation.centerTop:屏幕顶部中间
FloatingActionButtonLocation.endDocked:Dock右边
FloatingActionButtonLocation.endFloat:屏幕浮动右边
FloatingActionButtonLocation.endTop:屏幕顶部右边
FloatingActionButtonLocation.endContained:屏幕底部右边
FloatingActionButtonLocation.startDocked:Dock左边
FloatingActionButtonLocation.startFloat:屏幕浮动左边
FloatingActionButtonLocation.startTop:屏幕顶部左边

lib/pages/tabs.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import 'package:flutter/material.dart';
import './tabs/page_one.dart';
import './tabs/page_two.dart';

class Tabs extends StatefulWidget {
const Tabs({super.key});

@override
State<Tabs> createState() => _TabsState();
}

class _TabsState extends State<Tabs> {

int _currentIndex = 0;
final List<Widget> _pages = const [
PageOne(),
PageTwo(),
PageOne(),
PageTwo(),
PageOne(),
];

@override
Widget build(BuildContext context) {
return Scaffold(
body: _pages[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "PageOne",
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "PageTwo",
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "PageOne",
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "PageTwo",
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: "PageOne",
),
],
),
floatingActionButton: Container(
width: 60,
height: 60,
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30),
),
child: FloatingActionButton(
backgroundColor: _currentIndex==2?Colors.blue:Colors.black,
child: const Icon(Icons.add),
onPressed: () {
setState(() {
_currentIndex = 2;
});
},
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}

侧边栏

  • 侧边栏既可以通过点击菜单按钮展现,也可以通过从屏幕边缘向屏幕中间滑动展现

drawer:定义左侧侧边栏
endDrawer:定义右侧侧边栏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(),
drawer: const Drawer(
child: Text("左侧侧边栏"),
),
endDrawer: const Drawer(
child: Text("右侧侧边栏"),
),
),
));
}

菜单栏头部

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(),
drawer: const Drawer(
child: Column(
children: [
DrawerHeader(child: Text("左侧侧边栏"))
],
),
),
),
));
}

头部背景图占满侧边栏

通过Drawer实现

<url>:图片URL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(),
drawer: const Drawer(
child: Column(
children: [
Row(
children: [
Expanded(
flex: 1,
child: DrawerHeader(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage("<url>"),
fit: BoxFit.cover,
)
),
child: Text("左侧侧边栏")
),
)
],
)
],
),
),
),
));
}
通过UserAccountsDrawerHeader实现

accountName:定义用户名
accountEmail:定义用户邮箱
decoration:定义背景图
currentAccountPicture:定义用户当前头像
otherAccountsPictures:定义用户其他头像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(),
drawer: const Drawer(
child: Column(
children: [
Row(
children: [
Expanded(
flex: 1,
child: UserAccountsDrawerHeader(
accountName: Text("用户名"),
accountEmail: Text("邮箱"),
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage("<url>")
),
),
currentAccountPicture: CircleAvatar(
backgroundImage: NetworkImage("<url>"),
),
otherAccountsPictures: [
CircleAvatar(
backgroundImage: NetworkImage("<url>"),
),
CircleAvatar(
backgroundImage: NetworkImage("<url>"),
)
],
),
)
],
)
],
),
),
),
));
}

AppBar顶部导航栏

title:标题
leading:左侧图标,通常是菜单图标或返回图标
actions:右侧图标,可以定义多个
backgroundColor:背景颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("文本内容"),
leading: IconButton(
icon: const Icon(Icons.menu),
onPressed: () {},
),
actions: [
IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
)
],
backgroundColor: Colors.red,
),
),
));
}

实现通过顶部导航栏切换页面

  • TabControllerlength,与TabBartabs数量要保持一致
  • TabControllerlength,与TabBarViewchildren数量要保持一致

isScrollable:定义是否可以滚动
indicatorColor:指示器(当前选项卡底部的光标)的颜色
indicatorWeight:指示器的粗细
indicatorSize:指示器的长度

TabBarIndicatorSize.label:与文字等长
TabBarIndicatorSize.tab:与标签等长

indicator:指示器样式

color:指示器背景颜色
borderRadius:指示器圆角

labelColor:所有文字颜色
unselectedLabelColor:未选中文字颜色
labelStyle:文字样式

fontSize:字号

padding:边距

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import 'package:flutter/material.dart';

void main() {
runApp( const MaterialApp(
title: "文本内容",
home: App(),
));
}

class App extends StatefulWidget {
const App({super.key});

@override
State<App> createState() => _AppState();
}

class _AppState extends State<App> with SingleTickerProviderStateMixin {

late TabController _tabController;

@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("文本内容"),
bottom: TabBar(
controller: _tabController,
tabs: const [
Tab(
child: Text("文本标题1"),
),
Tab(
child: Text("文本标题2"),
),
Tab(
child: Text("文本标题3"),
),
],
isScrollable: true,
indicatorColor: Colors.white,
indicatorWeight: 2,
indicatorSize: TabBarIndicatorSize.tab,
indicator: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(5),
),
labelColor: Colors.red,
unselectedLabelColor: Colors.white,
labelStyle: const TextStyle(
fontSize: 20
),
padding: const EdgeInsets.all(5),
),
),
body: TabBarView(
controller: _tabController,
children: [
ListView(
children: const [
ListTile(
title: Text("文本内容1"),
),
],
),
ListView(
children: const [
ListTile(
title: Text("文本内容2"),
),
],
),
ListView(
children: const [
ListTile(
title: Text("文本内容3"),
),
],
),
],
),
);
}
}

获取当前选中的tab索引值

  • 监听tabController的改变事件,获取当前选中的tab索引值
1
2
3
4
5
6
7
8
9
10
11
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
// 监听tabController的改变事件,获取当前选中的tab索引值
_tabController.addListener(() {
if (_tabController.animation!.value == _tabController.index) {
print(_tabController.index);
}
});
}

销毁controller

1
2
3
4
5
@override
void dispose() {
super.dispose();
_tabController.dispose();
}

定义顶部导航栏高度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(50),
child: AppBar(
title: const Text("文本内容"),
),
),
),
));
}

定义顶部导航栏阴影

elevation:定义顶部导航栏阴影大小

1
2
3
4
5
6
7
8
9
10
11
12
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("文本内容"),
elevation: 10,
),
),
));
}

完成

参考文献

哔哩哔哩——筱筱知晓