一、初始化项目
- Material Design (Google 推出的前端UI 解决方案)
- Flutter 中一切内容都是组件(Widget)
- 无状态组件(StatelessWidget)
- 有状态组件(StatefulWidget)
二、app结构
- MaterialApp
- title (任务管理器中的标题)
- home (主内容)
- debugShowCheckedModeBanner (是否显示左上角调试标记)
- Scaffold
- appBar (应用头部)
- body (应用主体)
- float ingAct ionButton (浮按)
- drawer (左侧抽菜单)
- endDrawer (右侧抽菜单)
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("首页"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: HelloFlutter()
);
}
}
class HelloFlutter extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text(
"Hello Flutter",
textDirection: TextDirection.ltr,
)
)
);
}
}
三、文本组件Text
- Text
- TextDirection (文本方向)
- TextStyle (文本样式)
- Colors (文本颜色)
- FontWeight (字体细)
- FontStyle (字体样式)
- TextAlign (文本对齐)
- TextOverflow (文本出)
- maxLines (指定显示的行数)
- RichText与TextSpan
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Text"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: TextDemo()
);
}
}
class TextDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
children: [
Text(
"Flutter 是谷歌开发的一款开源、免费的,基于 Dart 语言的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生应用。",
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 30,
color: Colors.red,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.italic,
decoration: TextDecoration.lineThrough,
decorationColor: Colors.blue,
// fontFamily: 'SourceSansPro',
),
textAlign: TextAlign.left,
maxLines: 3,
overflow: TextOverflow.ellipsis,
textScaleFactor: 1.5,
),
RichText(
text: TextSpan(
text: "Hello",
style: TextStyle(
fontSize: 40,
color: Color.fromARGB(255, 0, 0, 255)
),
children: [
TextSpan(
text: "Flutter",
style: TextStyle(
fontSize: 40,
color: Color.fromRGBO(255, 0, 0, 0.5)
),
),
TextSpan(
text: "你好世界",
style: TextStyle(
fontSize: 30,
color: Color.fromARGB(0xFF, 0x00, 0xFF, 0x00)
),
)
]
),
)
],
);
}
}
四、设置自定义字体
- 下载并导入字体
- https://fonts.google.com/
- 加压压缩包,将字体文件复制到Flutter项目中
- 在pubspec.yaml中声明字体
- 使用
- 为整个应用设置默认自定义字体
- 为某个组件设置自定义字体
五、常用
- I con
- Flutter 中的图标库Icon (Icons. 具体名称)
- 在线预览
- https://material. io/resources/icons
六、color
- 布局- Container
- child (声明子组件)
- padding (margin)
- Edgelnsets (all(), fromLTRB(), only())
- decoration
- BoxDecoration (边框、圆角、渐变、阴影、背景色、背景图片)
- alignment
- Alignment (内容对齐)
- transform
- Matrix4 (移- translate,旋转 - rotate、缩放- scale、斜切 - skew)
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Text"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: ContainerDemo()
);
}
}
class ContainerDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
child: Text(
"Flutter 是谷歌开发的一款开源、免费的,基于 Dart 语言的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生应用。",
style: TextStyle(
fontSize: 20
),
),
// width: 200,
// height: 200,
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.fromLTRB(10.0, 30.0, 0.0, 5.0),
);
}
}
七、container-盒子
- child(声明子组件)
- padding (margin)
- Edgelnsets (all()、 fromLTRB()、 only())
- decoration
- BoxDecoration(边框、圆角、渐变、阴影、背景色、背景图
- alignment
- Alignment (内容对齐)
- transform
- Matrix4(平移 -translate、旋转-rotate、缩放 -scale、斜切 -skew)
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Text"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: ContainerDemo()
);
}
}
class ContainerDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
child: Text(
"Flutter 是谷歌开发的一款开源、免费的,基于 Dart 语言的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生应用。",
style: TextStyle(
fontSize: 20
),
),
// width: 200,
// height: 200,
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.fromLTRB(10.0, 30.0, 0.0, 5.0),
);
}
}
八、布局-线性布局
- Column
- Column 中的主轴方向是垂直方
- mainAxisAlignment:MainAxisAlignment 主轴对齐方
- crossAxisAlignment: CrossAxisAlignment 交叉抽对齐方式
- children: 内容
- Row
- Row 中的主轴方向是水平方向(其他属性与 Column 一致)
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Column_Row"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: ColumnRowDemo()
);
}
}
class ColumnRowDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
color: Colors.lightGreen,
width: double.infinity,
child: Column(
// 主轴的对齐方式
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// 交叉轴的对齐方式
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.access_alarms, size: 50),
Icon(Icons.accessible_forward_rounded, size: 50),
Icon(Icons.settings, size: 50),
Icon(Icons.add_box, size: 50),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(Icons.access_alarms, size: 50),
Icon(Icons.accessible_forward_rounded, size: 50),
Icon(Icons.settings, size: 50),
Icon(Icons.add_box, size: 50),
],
),
],
)
);
}
}
九、布局-弹性布局
- Flex
- direction (声明主轴方向)
- mainAxisAlignment (声明主轴对齐方式)
- textDirection (声明水平方向的排列顺序)
- crossAxisAlignment (声明交叉轴对齐方式)
- verticalDirection (声明垂直方向的排列顺序)
- children (声明子组件)
- Expanded (可伸缩组件)
- flex (声明弹性布局所占比例
- child (声明子组件)
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flex"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: FlexDemo()
);
}
}
class FlexDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
children: [
// 验证 Expanded
Row(
children: [
Container(
color: Colors.lightBlue,
height: 50,
width: 50,
),
Expanded(
child: Container(
color: Colors.lightGreen,
height: 50,
),
)
],
),
Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceAround,
// 声明水平方向的排列方式
textDirection: TextDirection.rtl,
children: [
Icon(Icons.access_alarms, size: 50),
Icon(Icons.accessible_forward_rounded, size: 50),
Icon(Icons.settings, size: 50),
Icon(Icons.add_box, size: 50),
],
),
Flex(
direction: Axis.horizontal,
children: [
Expanded(
child: Container(
color: Colors.tealAccent,
height: 50,
),
flex: 2,
),
Expanded(
child: Container(
color: Colors.amberAccent,
height: 50,
),
flex: 1,
)
],
),
Container(
height: 100,
margin: EdgeInsets.all(50),
child: Flex(
direction: Axis.vertical,
verticalDirection: VerticalDirection.up,
children: [
Expanded(
child: Container(
color: Colors.tealAccent,
height: 50,
),
flex: 2,
),
// Spacer(
// flex: 1
// ),
Expanded(
child: Container(
color: Colors.amberAccent,
height: 50,
),
flex: 1,
)
],
),
),
],
);
}
}
十、布局-流式布局
- Wrap(解决内容溢出问题)
- spacing(主轴方向子组件的间距)
- alignment (主轴方向的对齐方式)
- runSpacing(纵轴方向子组件的间距)
- runAlignment (纵轴方向的对齐方式)
- Chip (标签)
- CircleAvatar (圆形头像)
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Wrap"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: WrapDemo()
);
}
}
class WrapDemo extends StatelessWidget {
List<String> _list = [
'曹操', '司马懿', '曹仁', '曹洪', '张辽', '许褚'
];
List<Widget> _weiGuo() {
return _list.map((item) => Chip(
avatar: CircleAvatar(
backgroundColor: Colors.pink,
child: Text('魏'),
),
label: Text(item),
)).toList();
}
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Wrap(
children: _weiGuo(),
spacing: 18.0, // 水平方向的间距
alignment: WrapAlignment.spaceAround, // 主轴方向的对齐方式
runSpacing: 100, // 垂直方向的间距
// runAlignment: WrapAlignment.spaceAround, // 交叉轴方向i的对齐方式
),
Wrap(
children: [
Chip(
avatar: CircleAvatar(
backgroundColor: Colors.blue,
child: Text('蜀'),
),
label: Text('刘备'),
),
Chip(
avatar: CircleAvatar(
backgroundColor: Colors.blue,
child: Text('蜀'),
),
label: Text('关羽'),
),
Chip(
avatar: CircleAvatar(
backgroundColor: Colors.blue,
child: Text('蜀'),
),
label: Text('张飞'),
),
Chip(
avatar: CircleAvatar(
backgroundColor: Colors.blue,
child: Text('蜀'),
),
label: Text('赵云'),
),
Chip(
avatar: CircleAvatar(
backgroundColor: Colors.blue,
child: Text('蜀'),
),
label: Text('诸葛亮'),
),
Chip(
avatar: CircleAvatar(
backgroundColor: Colors.blue,
child: Text('蜀'),
),
label: Text('黄忠'),
),
],
),
],
);
}
}
十一、布局-层叠布局
- Stack (层叠组件-类似 css 中的 z-index)
- alignment (声明未定位子组件的对齐方式)
- textDirection (声明未定位子组件的排列顺序)
- Positioned (绝对定位组件)
- child (声明子组件)
- left、 top、 right、 bottom
- width、 height
- Networklmage (网络图片组件)
- Networklmage(‘图片地址’)
- <uses-permission android:name=“android.permission.INTERNET” />
配置网络图片访问权限
设置允许访问http协议
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("层叠布局"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: StackDemo()
);
}
}
class StackDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
child: Stack(
// 声明未定位的子组件的排序方式
textDirection: TextDirection.rtl,
// 声明未定位的子组件的对齐方式
alignment: AlignmentDirectional.bottomEnd,
children: [
CircleAvatar(
backgroundImage: NetworkImage('http://img12.360buyimg.com/n1/jfs/t1/133894/17/20175/388796/5fdb4134E17deda69/15535fe4303a1630.png'),
radius: 200,
),
Positioned(
child: Container(
color: Colors.red,
padding: EdgeInsets.all(10),
child: Text(
'热卖',
style: TextStyle(
color: Colors.white,
fontSize: 20
),
)
),
top: 50,
right: 40
),
Text(
'Hello',
style: TextStyle(
color: Colors.black,
fontSize: 40
),
)
],
)
);
}
}
十二、布局-Card
- Card(卡片)
- child 子组件
- color 背景色
- shadowColor 阴影色
- elevation 阴影高度
- shape 边框样式
- margin 外边距
- ListTile (列表瓦片)
- leading(头部组件)
- title (标题)
- subtitle (子标题)
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("卡片"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: CardDemo()
);
}
}
class CardDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
children: [
Card(
margin: EdgeInsets.all(30),
color: Colors.purpleAccent[100],
shadowColor: Colors.yellow, // 阴影颜色
elevation: 20, // 阴影高度
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
side: BorderSide(
color: Colors.yellow,
width: 3,
),
),
child: Column(
children: [
ListTile(
leading: Icon(
Icons.supervised_user_circle_rounded,
size: 50
),
title: Text(
"张三",
style: TextStyle(
fontSize: 30
),
),
subtitle: Text(
"董事长",
style: TextStyle(
fontSize: 20
),
),
),
Divider(),
ListTile(
title: Text(
"电话:13333333333",
style: TextStyle(
fontSize: 20
),
),
),
ListTile(
title: Text(
"地址:XXXXXXXX",
style: TextStyle(
fontSize: 20
),
),
)
],
)
),
Card(
margin: EdgeInsets.all(30),
child: Column(
children: [
ListTile(
leading: Icon(
Icons.supervised_user_circle_rounded,
size: 50
),
title: Text(
"李四",
style: TextStyle(
fontSize: 30
),
),
subtitle: Text(
"总经理",
style: TextStyle(
fontSize: 20
),
),
),
Divider(),
ListTile(
title: Text(
"电话:13333333333",
style: TextStyle(
fontSize: 20
),
),
),
ListTile(
title: Text(
"地址:XXXXXXXX",
style: TextStyle(
fontSize: 20
),
),
)
],
)
)
],
);
}
}
效果:
十三、按钮
- Flutter 1.22之前
- FlatButton(扁平按钮)
- RaisedButton (凸起按钮)
- OutlineButton (轮廓按钮)
- Flutter 1.22之后
- TextButton (文本按钮-用来替换 FlatButton)
- ElevatedButton (凸起按钮-用来替换 RaisedButton)
- OutlinedButton(轮廓按钮-用来替换 OutlineButton)
旧按钮 vs 新按钮
为什么会新增按钮?
以前的按钮调整为统一的外观比较麻烦,经常自定义大量按钮样式新按钮将外观属性集合为一个 ButtonStyle,非常方便统一控制。
按钮
- 图标按钮
- IconButton
- TextButton.icon()
- ElevatedButton.icon()
- OutlinedButton.icon()
- ButtonBar (按钮组)
- FloatingActionButton (浮动按钮)
- BackButton (回退按钮)
- CloseButton (关闭按钮)
import 'dart:ui';
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Button"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: ButtonDemo(),
floatingActionButton: FloatingActionButton(
onPressed: (){},
tooltip: 'Increment',
child: Icon(Icons.add),
backgroundColor: Colors.green,
elevation: 0,
),
);
}
}
class ButtonDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
child: Wrap(
children: [
TextButton(
onPressed: () {
print('点击 TextButton');
},
onLongPress: () {
print('长按 TextButton');
},
child: Text('TextButton')
),
ElevatedButton(
onPressed: () {
print('点击 ElevatedButton');
},
onLongPress: () {
print('长按 ElevatedButton');
},
child: Text('ElevatedButton')
),
OutlinedButton(
onPressed: () {
print('点击 OutlinedButton');
},
onLongPress: () {
print('长按 OutlinedButton');
},
child: Text('OutlinedButton')
),
OutlinedButton(
onPressed: () {
print('点击 OutlinedButton');
},
onLongPress: () {
print('长按 OutlinedButton');
},
child: Text('轮廓按钮'),
style: ButtonStyle(
textStyle: MaterialStateProperty.all(
TextStyle(
fontSize: 30
)
),
foregroundColor: MaterialStateProperty.resolveWith((states) {
if (states.contains(MaterialState.pressed)) {
// 按下按钮时的前景色
return Colors.red;
}
// 默认状态的颜色
return Colors.blue;
}),
backgroundColor: MaterialStateProperty.resolveWith((states) {
if (states.contains(MaterialState.pressed)) {
// 按下按钮时的前景色
return Colors.yellow;
}
// 默认状态的颜色
return Colors.white;
}),
shadowColor: MaterialStateProperty.all(Colors.yellow),
elevation: MaterialStateProperty.all(20),
side: MaterialStateProperty.all(
BorderSide(
color: Colors.green,
width: 2,
)
),
// 声明按钮形状
shape: MaterialStateProperty.all(
StadiumBorder(
side: BorderSide(
color: Colors.green,
width: 2,
)
)
),
// 设置按钮大小
minimumSize: MaterialStateProperty.all(Size(200, 100)),
// 设置水波纹的颜色
overlayColor: MaterialStateProperty.all(Colors.purple),
)
),
OutlinedButtonTheme(
data: OutlinedButtonThemeData(
style: ButtonStyle(
overlayColor: MaterialStateProperty.all(Colors.red),
)
),
child: OutlinedButton(
onPressed: () {
print('点击 OutlinedButton');
},
onLongPress: () {
print('长按 OutlinedButton');
},
child: Text('轮廓按钮'),
style: ButtonStyle(
overlayColor: MaterialStateProperty.all(Colors.blue),
)
)
),
// 图标按钮
IconButton(
icon: Icon(Icons.add_alarm),
onPressed: () {
print('IconButton');
},
color: Colors.red,
splashColor: Colors.lightBlue,
highlightColor: Colors.purple,
tooltip: "怎么了",
),
TextButton.icon(
icon: Icon(Icons.add_circle),
label: Text('文本按钮'),
onPressed: () {
},
),
ElevatedButton.icon(
icon: Icon(Icons.add_circle),
label: Text('凸起按钮'),
onPressed: () {
},
),
OutlinedButton.icon(
icon: Icon(Icons.add_circle),
label: Text('轮廓按钮'),
onPressed: () {
},
),
// 按钮组
Container(
color: Colors.pink[100],
width: double.infinity,
child: ButtonBar(
children: [
ElevatedButton(
onPressed: (){},
child: Text('按钮一'),
),
ElevatedButton(
onPressed: (){},
child: Text('按钮二'),
),
ElevatedButton(
onPressed: (){},
child: Text('按钮二'),
),
ElevatedButton(
onPressed: (){},
child: Text('按钮二'),
),
ElevatedButton(
onPressed: (){},
child: Text('按钮二'),
),
],
)
),
BackButton(
color: Colors.red,
onPressed: () {},
),
CloseButton(
color: Colors.red,
onPressed: () {},
),
],
)
);
}
}
效果:
十四、图片
- Image.asset (加载本地图片)
- Flutter 项目下,创建图片存储目录
- 在 pubspec.yaml 中的 flutter 部分添加图片配置
- 在代码中加载图片
- Image.network (加载网络图片)保证网络畅通
- 设置网络访问权限
- 允许 http 协议访问
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Image"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: ImageDemo()
);
}
}
class ImageDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
children: [
// 加载本地图片
Image.asset(
'images/bg1.jpg',
width: 200,
height: 200,
fit: BoxFit.fill,
),
// 加载网络图片
Image.network(
'http://cdn.cnbj1.fds.api.mi-img.com/mi-mall/5a260090e0e08770b0bd865845a4b4ab.jpg',
repeat: ImageRepeat.repeat,
colorBlendMode: BlendMode.colorDodge,
color: Colors.green,
),
],
);
}
}
十五、列表-SingleChildScrollView
- SingleChildScrollView (类似Android中的 ScrollView)
- child (子组件)
- padding (内边距)
- scrollDirection (滚动方向: Axis.horizontal | Axis.vertical)
- reverse(初始滚动位置,false 头部、true 尾部)
- physics
- ClampingScrollPhysics: Android 下微光效果
- BouncingScrollPhysics: ios 下弹性效果
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SingleChildScrollView"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: SingleChildScrollViewDemo()
);
}
}
class SingleChildScrollViewDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Stack(
children: [
// 验证水平滚动
SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.all(10),
reverse: true,
child: Row(
children: [
OutlinedButton(
onPressed: () {},
child: Text('按钮一')
),
OutlinedButton(
onPressed: () {},
child: Text('按钮二')
),
OutlinedButton(
onPressed: () {},
child: Text('按钮三')
),
OutlinedButton(
onPressed: () {},
child: Text('按钮四')
),
OutlinedButton(
onPressed: () {},
child: Text('按钮五')
),
OutlinedButton(
onPressed: () {},
child: Text('按钮六')
),
]
),
),
// 垂直方向的滚动
SingleChildScrollView(
scrollDirection: Axis.vertical,
padding: EdgeInsets.all(10),
reverse: true,
physics: BouncingScrollPhysics(),
child: Column(
children: List.generate(
100,
(index) => OutlinedButton(
onPressed: () {},
child: Text('按钮$index')
),
)
),
)
],
);
}
}
十六、列表-ListView
- ListView
- 加载列表的组件(加载所有 Widgets,适用 Widget 较少的场景)
- ListTile (leading、 title、 subtitle、 trailing、 selected)
- ListView.builder
- 按需加载 Widget,性能比默认构造函数高,适用 Widget 较多的场景
- ListView.separated
- 比 ListView.builder 多了分隔器
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ListView"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: ListViewDemo()
);
}
}
class ListViewDemo extends StatelessWidget {
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
ListViewBasic(),
ListViewHorizontal(),
ListViewBuilderDemo(),
ListViewSeperatedDemo(),
]
)
);
}
}
class ListViewBasic extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
height: 200,
child: ListView(
scrollDirection: Axis.vertical,
children: [
ListTile(
leading: Icon(Icons.access_alarm, size: 50),
title: Text('access_alarm'),
subtitle: Text('子标题'),
trailing: Icon(Icons.keyboard_arrow_right),
),
ListTile(
leading: Icon(Icons.ac_unit, size: 50),
title: Text('ac_unit'),
subtitle: Text('子标题'),
trailing: Icon(Icons.keyboard_arrow_right),
selected: true,
selectedTileColor: Colors.red[100],
),
ListTile(
leading: Icon(Icons.add_photo_alternate_rounded, size: 50),
title: Text('add_photo_alternate_rounded'),
subtitle: Text('子标题'),
trailing: Icon(Icons.keyboard_arrow_right),
),
ListTile(
leading: Icon(Icons.fact_check_outlined, size: 50),
title: Text('fact_check_outlined'),
subtitle: Text('子标题'),
trailing: Icon(Icons.keyboard_arrow_right),
),
]
)
);
}
}
class ListViewHorizontal extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
height: 100,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(
width: 160,
color: Colors.amber,
),
Container(
width: 160,
color: Colors.blueAccent,
),
Container(
width: 160,
color: Colors.black87,
),
Container(
width: 160,
color: Colors.grey,
),
],
)
);
}
}
class ListViewBuilderDemo extends StatelessWidget {
final List<Widget> users = new List<Widget>.generate(20, (index) => OutlinedButton(
onPressed: () {},
child: Text('姓名 $index')
));
Widget build(BuildContext context) {
return Container(
height: 150,
child: ListView.builder(
itemCount: users.length,
itemExtent: 30,
padding: EdgeInsets.all(10),
itemBuilder: (context, index) {
return users[index];
},
)
);
}
}
class ListViewSeperatedDemo extends StatelessWidget {
final List<Widget> products = List.generate(20, (index) => ListTile(
leading: Image.asset('images/flutter.jpg'),
title: Text('商品标题 $index'),
subtitle: Text('子标题'),
trailing: Icon(Icons.keyboard_arrow_right),
));
Widget build(BuildContext context) {
Widget dividerOdd = Divider(
color: Colors.blue,
thickness: 2
);
Widget dividerEven = Divider(
color: Colors.red,
thickness: 2
);
return Column(
children: [
ListTile(
title: Text('商品列表'),
),
Container(
height: 200,
child: ListView.separated(
itemCount: products.length,
itemBuilder: (context, index) {
return products[index];
},
// 分隔器的构造器
separatorBuilder: (context, index) {
return index%2 == 0 ? dividerEven : dividerOdd;
},
)
),
],
);
}
}
效果:
十七、列表-GridView-上
- GridView (网格布局)
- children (子组件)
- scrollDirection (滚动方向)
- gridDelegate
- SliverGridDelegateWithFixedCrossAxisCount (指定列数- 子组件宽度自适应)
- SliverGridDelegateWithMaxCrossAxisExtent (指定子组件宽度 - 列数自适应)
- GridView.count (列数固定)
- GridView.extend (子组件宽度固定)
- GridView.builder (动态网格布局)
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("GridView"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: GridViewDemo()
);
}
}
class GridViewDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(10),
child:
// GridView(
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 2, // 指定列数
// mainAxisSpacing: 20, // 主轴方向的间距
// crossAxisSpacing: 10, // 交叉轴的间距
// childAspectRatio: 1.5, // 子组件的宽高比例
// ),
// children: [
// Container(color: Colors.tealAccent),
// Container(color: Colors.amberAccent),
// Container(color: Colors.redAccent),
// Container(color: Colors.blueGrey),
// Container(color: Colors.purpleAccent),
// Container(color: Colors.lightGreenAccent),
// Container(color: Colors.lightGreen),
// Container(color: Colors.black54),
// Container(color: Colors.yellowAccent),
// Container(color: Colors.grey),
// Container(color: Colors.deepOrangeAccent),
// ],
// ),
GridView(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 190, // 子组件的宽度
mainAxisSpacing: 30,
crossAxisSpacing: 10,
childAspectRatio: 0.8,
),
children: [
Container(color: Colors.tealAccent),
Container(color: Colors.amberAccent),
Container(color: Colors.redAccent),
Container(color: Colors.blueGrey),
Container(color: Colors.purpleAccent),
Container(color: Colors.lightGreenAccent),
Container(color: Colors.lightGreen),
Container(color: Colors.black54),
Container(color: Colors.yellowAccent),
Container(color: Colors.grey),
Container(color: Colors.deepOrangeAccent),
],
)
);
}
}
效果:
十八、列表-GridView-下
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("GridView"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: GridViewBuilderDemo()
);
}
}
class GridViewCountDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
child: GridView.count(
children: List.generate(10, (index) =>
Image.asset('images/flutter.jpg')
),
crossAxisCount: 2,
mainAxisSpacing: 20,
crossAxisSpacing: 20,
padding: EdgeInsets.symmetric(horizontal: 40),
childAspectRatio: 1.5,
),
);
}
}
class GridViewExtendDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
child: GridView.extent(
children: List.generate(10, (index) =>
Image.asset('images/flutter.jpg')
),
maxCrossAxisExtent: 100, // 子组件的宽度
mainAxisSpacing: 20,
crossAxisSpacing: 20,
padding: EdgeInsets.symmetric(horizontal: 40),
// childAspectRatio: 1.5,
),
);
}
}
class GridViewBuilderDemo extends StatelessWidget {
final List<dynamic> _tiles = [
Container(color: Colors.tealAccent),
Container(color: Colors.amberAccent),
Container(color: Colors.redAccent),
Container(color: Colors.blueGrey),
Container(color: Colors.purpleAccent),
Container(color: Colors.lightGreenAccent),
Container(color: Colors.lightGreen),
Container(color: Colors.black54),
Container(color: Colors.yellowAccent),
Container(color: Colors.grey),
Container(color: Colors.deepOrangeAccent),
];
Widget build(BuildContext context) {
return Container(
child: GridView.builder(
padding: EdgeInsets.symmetric(horizontal: 40),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 20,
crossAxisSpacing: 20,
childAspectRatio: 1.0
),
itemCount: _tiles.length,
itemBuilder: (context, index) {
return _tiles[index];
},
physics: BouncingScrollPhysics(), // 反弹效果
// physics: ClampingScrollPhysics(), // 夹住的效果
// physics: AlwaysScrollableScrollPhysics(), // 滚动
// physics: NeverScrollableScrollPhysics(), // 禁止滚动
),
);
}
}
十九、其他-Cupertino- ios风格组件
- Material
- 安卓风格的组件
- import ‘package:flutter/material.dart’;
- Cupertino
- ios 风格的组件
- import ‘package:flutter/cupertino.dart’;
- https://flutter.dev/docs/development/ui/widgets/cupertino
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:io';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Cupertino"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: MyBody()
);
}
}
class MyBody extends StatelessWidget {
Widget build(BuildContext context) {
Widget dialogBox;
// 判断当前的平台信息
if (Platform.isIOS) {
// 加载 iOS 风格的组件
dialogBox = CupertinoDemo();
} else if (Platform.isAndroid) {
// 加载 Android 风格的组件
dialogBox = MaterialDemo();
}
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// 安装风格的组件
Text('Material - 安卓风格'),
MaterialDemo(),
// iOS 风格的组件
Text('Cupertino - iOS 风格'),
CupertinoDemo()
]
)
);
}
}
class MaterialDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
child: AlertDialog(
title: Text('提示'),
content: Text('确认删除吗?'),
actions: [
TextButton(
child: Text('取消'),
onPressed: () {
print('取消的逻辑');
}
),
TextButton(
child: Text('确认'),
onPressed: () {
print('确认的逻辑');
}
),
]
)
);
}
}
class CupertinoDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
child: CupertinoAlertDialog(
title: Text('提示'),
content: Text('确认删除吗?'),
actions: [
CupertinoDialogAction(
child: Text('取消'),
onPressed: () {
print('取消的逻辑');
}
),
CupertinoDialogAction(
child: Text('确认'),
onPressed: () {
print('确认的逻辑');
}
)
],
)
);
}
}
二十、SafeArea
- SafeArea可以有效解决异形屏幕的问题(刘海屏)
二十一、第三方组件-dio
- dio
- flutter-swiper
- shared_preferences
dio
- dio 是一个强大的 Dart Http 请求库(类似 axios)
- https://pub.dev/packages/dio
- 使用步骤
- 在 pubsepc.yaml 中添加 dio 依赖
- 安装依赖(pub get | flutter packages get | VS Code 中保存配置,自动下载)
- 引入 import ‘package:dio/dio.dart’;
- 使用:https://pub.dev/documentation/dio/latest/
get请求:
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dio"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: DioDemo()
);
}
}
class DioDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
child: Text('点击发送请求'),
onPressed: () {
// 调用 HTTP 请求
getIpAddress();
}
),
);
}
void getIpAddress() async {
try {
final url = "https://httpbin.org/ip";
Response response = await Dio().get(url);
String ip = response.data['origin'];
print(ip);
} catch (e) {
print(e);
}
}
}
二十二、Flutter_swiper
- Flutter 中最好的轮播组件,适配 Android 和 iOs
- https://pub.dev/packages/flutter_swiper
- 使用步骤
- 在 pubsepc.yaml 中添加 flutter_swiper 依赖
- 安装依赖(pub get | flutter packages get | VS Code 中保存配置,自动下载)
- 引入 import ‘package:flutter_swiper/flutter_swiper.dart’;
- 使用
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
class Home extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("flutter_swiper"),
leading: Icon(Icons.menu),
actions: [
Icon(Icons.settings)
],
elevation: 0.0,
centerTitle: true,
),
body: FlutterSwiperDemo()
);
}
}
class FlutterSwiperDemo extends StatelessWidget {
final List<String> imgs = [
'images/1.jpg',
'images/2.jpg',
'images/3.jpg',
];
Widget build(BuildContext context) {
return ListView(
children: [
Container(
height: 200,
child: Swiper(
itemCount: imgs.length,
itemBuilder: (context, index) {
return Image.asset(
imgs[index],
fit: BoxFit.cover
);
},
pagination: SwiperPagination(), // 轮播图的指示点
control: SwiperControl(),// 左右箭头导航
),
),
Container(
height: 200,
child: Swiper(
itemCount: imgs.length,
itemBuilder: (context, index) {
return Image.asset(
imgs[index],
fit: BoxFit.cover
);
},
viewportFraction: 0.7,
scale: 0.7,
),
),
Container(
height: 200,
child: Swiper(
itemCount: imgs.length,
itemBuilder: (context, index) {
return Image.asset(
imgs[index],
fit: BoxFit.cover
);
},
itemWidth: 300,
layout: SwiperLayout.STACK,
),
),
Container(
height: 200,
child: Swiper(
itemCount: imgs.length,
itemBuilder: (context, index) {
return Image.asset(
imgs[index],
fit: BoxFit.cover
);
},
itemWidth: 300,
itemHeight: 200,
layout: SwiperLayout.TINDER,
),
)
],
);
}
}