【Flutter】教程-组件分析
本文介绍了Flutter中的常用组件,包括按钮组件(如普通按钮、文本按钮、边框按钮、图文按钮及其样式自定义)、Center与Align组件的居中与定位功能,以及Container容器的布局属性(宽高、边距、圆角等)。通过代码示例展示了如何实现不同样式按钮和容器布局,并提供了组件生成的快捷方式截图。这些基础组件是构建Flutter应用界面时的重要工具。
·
【Flutter】教程
flutter组件
按钮组件

//按钮示例
class Buttonpage extends StatelessWidget {
const Buttonpage({super.key});
@override
Widget build(BuildContext context) {
return ListView(children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
onPressed: () {
print(1);
},
child: Text('普通按钮')),
TextButton(
onPressed: () {
print(1);
},
child: Text('文本按钮')),
OutlinedButton(
style: ButtonStyle(
side: WidgetStateProperty.all(
BorderSide(
width: 1,
color: Colors.red
)
)
),
onPressed: null,
child: Text('边框按钮')),
IconButton(onPressed: null, icon: Icon(Icons.thumb_up))
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton.icon(
onPressed: () {},
icon: Icon(Icons.send),
label: Text('发送(图文按钮)'),
),
TextButton.icon(
onPressed: () {},
icon: Icon(Icons.info),
label: Text('消息(图文按钮)'),
),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
OutlinedButton.icon(
onPressed: () {},
icon: Icon(Icons.add),
label: Text('增加(图文按钮)'),
),
ElevatedButton(
style: ButtonStyle(
//背景颜色
backgroundColor: WidgetStateProperty.all(Colors.red[50]),
//文字颜色
foregroundColor: WidgetStateProperty.all(Colors.black),
),
onPressed: () {},
child: Text('样式按钮'),
),
],
),
SizedBox(height: 20),
//修改宽高,圆角的按钮
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(
width: 200,
height: 60,
child: ElevatedButton(
style: ButtonStyle(
shape: WidgetStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20))),
//背景颜色
backgroundColor: WidgetStateProperty.all(Colors.red[50]),
//文字颜色
foregroundColor: WidgetStateProperty.all(Colors.black),
),
onPressed: () {},
child: Text('自定义宽高,圆角按钮'),
),
)
],
),
SizedBox(height: 20),
//自适应宽的按钮
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
flex: 1,
child: Container(
margin: EdgeInsets.all(20),
height: 60,
child: ElevatedButton(
style: ButtonStyle(
//背景颜色
backgroundColor: WidgetStateProperty.all(Colors.red[50]),
//文字颜色
foregroundColor: WidgetStateProperty.all(Colors.black),
),
onPressed: () {},
child: Text('自适应按钮'),
),
))
],
)
]);
}
}
Center组件
- 可让子组件居中
Align组件
- 可以调整子组件的位置
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.topLeft,
child: new Text(
"你好 flutter3",
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.red, fontSize: 30.0, fontWeight: FontWeight.w800),
),
);
}
}

Container容器组件
- Container是flutter很常用的组件,类似html的div
- 它可以设置width,height,padding,margin,border



- 这个是生成组件的快捷

class MyContainer extends StatelessWidget {
const MyContainer({super.key});
@override
Widget build(BuildContext context) {
return Container(
width: 250,
height: 250,
// 内容位置
// alignment: Alignment.center,
padding: EdgeInsets.all(24),
// 仅仅配置几边
margin: EdgeInsets.only(left: 30, top: 20),
decoration: BoxDecoration(
color: Colors.blue,
// 圆角
borderRadius: BorderRadius.circular(20),
// 边框
border: Border.all(color: Colors.black, width: 2),
// 阴影
boxShadow: [BoxShadow(color: Colors.black45, blurRadius: 20)]),
child: Text(
"你好 flutter子组件",
textDirection: TextDirection.ltr,
style: TextStyle(
color: Colors.red, fontSize: 20.0, fontWeight: FontWeight.w800),
),
);
}
}

Text组件



Row水平布局组件

- 宽高等于屏幕的高度
- width:double.infinity
- height:double.infinity
class MyRow extends StatelessWidget {
const MyRow({super.key});
@override
Widget build(BuildContext context) {
return Container(
width: 500,
height: 700,
color: Colors.black12,
child: Row(
//水平布局位置
mainAxisAlignment:MainAxisAlignment.spaceBetween,
children: [
Container(
width: 100,
height: 100,
color: Colors.red,
child: Icon(
Icons.home,
color: Colors.white,
size: 40,
),
),
Container(
width: 100,
height: 100,
color: const Color.fromARGB(255, 89, 49, 129),
child: Icon(
Icons.search,
color: Colors.white,
size: 40,
),
),
Container(
width: 100,
height: 100,
color: const Color.fromARGB(255, 89, 196, 178),
child: Icon(
Icons.send,
color: Colors.white,
),
)
],
),
);
}
}
Column垂直布局组件
- 属性和Row属性基本一致
class MyColumn extends StatelessWidget {
const MyColumn({super.key});
@override
Widget build(BuildContext context) {
return Container(
width: 500,
height: 700,
color: Colors.black12,
child: Column(
// 水平布局位置
mainAxisAlignment:MainAxisAlignment.spaceBetween,
// 次轴布局
crossAxisAlignment:CrossAxisAlignment.center,
children: [
Container(
width: 100,
height: 100,
color: Colors.red,
child: Icon(
Icons.home,
color: Colors.white,
size: 40,
),
),
Container(
width: 100,
height: 100,
color: const Color.fromARGB(255, 89, 49, 129),
child: Icon(
Icons.search,
color: Colors.white,
size: 40,
),
),
Container(
width: 100,
height: 100,
color: const Color.fromARGB(255, 89, 196, 178),
child: Icon(
Icons.send,
color: Colors.white,
),
)
],
),
);
}
}

ListView可滚动的列表组件
- 导入字体图标后需执行flutter pub get,确保字体文件被正确引入到项目
- 如何导入图标
- 将.ttf文件放入项目中
- pubspec.yaml文件中处理一下
fonts:
- family: jiqiren
fonts:
- asset: assets/jiqiren.ttf
- 新建myIconsFont.dart文件
import 'package:flutter/material.dart';
class MyIcons{
static const IconData jiqiren =IconData(
0xe60c,
fontFamily: 'MyIcons',
matchTextDirection: true
);
}
class MyListView extends StatelessWidget {
const MyListView({super.key});
@override
Widget build(BuildContext context) {
return Container(
width: 500,
height: 700,
color: Colors.black12,
child: ListView(
children: [
ListTile(
leading: Icon(MyIcons.jiqiren,color:Colors.blue),
title: Text("我的"),
),
Divider(),
ListTile(
title: Text("机器右边箭头图标"),
trailing: Icon(Icons.chevron_right_sharp),
),
Divider(),
],
),
);
}
}
padding组件
- 作用就是给 child内容加padding值
- 比Container组件占用内存更小
- 属性:
- padding
- child
// padding组件
// 方式1,不用padding组件
class pagePadding extends StatelessWidget {
const pagePadding({super.key});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(32),
child: const Text("你好flutter"),
);
}
}
class pagePadding2 extends StatelessWidget {
const pagePadding2({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(32),
child: const Text("你好flutter"),
);
}
}
GridView网格布局组件

三种实现方式
- GridView.count实现网格布局
- GridView.exent实现网格布局
- GridView.builder实现动态网格布局

import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "万物互联",
theme: ThemeData(
primaryColor: Colors.blue,
),
home:
Scaffold(appBar: AppBar(title: const Text('网格系统')), body: twoPage()),
);
}
}
// 方式1 GridView.count
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
// crossAxisCount主轴数量
return GridView.count(crossAxisCount: 3, children: [
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike)
]);
}
}
// 方式2 GridView.extent
class twoPage extends StatelessWidget {
const twoPage({super.key});
@override
Widget build(BuildContext context) {
// maxCrossAxisExtent,横轴每个子元素最大长度
return GridView.extent(
maxCrossAxisExtent: 140,
crossAxisSpacing: 20, //水平widget之间间距
mainAxisSpacing: 20, //垂直widget之间间距
padding: EdgeInsets.all(10),
childAspectRatio: 0.8, //宽高比例
children: [
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike),
Icon(Icons.pedal_bike)
]);
}
}
// 方式3 GridView.builder
class threePage extends StatelessWidget {
const threePage({super.key});
static const listData = [
{"title": "one", "img": "http://tian-ji.sunyay.cn:9999/uploads/82.png"},
{"title": "two", "img": "http://tian-ji.sunyay.cn:9999/uploads/82.png"},
{"title": "three", "img": "http://tian-ji.sunyay.cn:9999/uploads/82.png"}
];
Widget _initThreeList(context, index) {
//循环数组2
return Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color.fromARGB(255, 44, 145, 133),
border: Border.all(color: Colors.black12)),
child: Column(
children: [
Image.network(listData[index]["img"]!),
const SizedBox(height: 10),
Text(
listData[index]["title"]!,
style: TextStyle(fontSize: 18),
)
],
));
}
@override
Widget build(BuildContext context) {
// SliverGridDelegateWithFixedCrossAxisCount,相当于GridView.count
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 20,
mainAxisSpacing: 20,
crossAxisCount: 2,//必传
childAspectRatio: 0.8, //宽高比例
),
itemCount: listData.length,//必传
itemBuilder: _initThreeList);
}
}
// 方式3 GridView.builder
class fourPage extends StatelessWidget {
const fourPage({super.key});
static const listData = [
{"title": "one", "img": "http://tian-ji.sunyay.cn:9999/uploads/82.png"},
{"title": "two", "img": "http://tian-ji.sunyay.cn:9999/uploads/82.png"},
{"title": "three", "img": "http://tian-ji.sunyay.cn:9999/uploads/82.png"}
];
Widget _initThreeList(context, index) {
//循环数组2
return Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color.fromARGB(255, 44, 145, 133),
border: Border.all(color: Colors.black12)),
child: Column(
children: [
Image.network(listData[index]["img"]!),
const SizedBox(height: 10),
Text(
listData[index]["title"]!,
style: TextStyle(fontSize: 18),
)
],
));
}
@override
Widget build(BuildContext context) {
// SliverGridDelegateWithMaxCrossAxisExtent,相当于GridView.extent
return GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
crossAxisSpacing: 20,
mainAxisSpacing: 20,
maxCrossAxisExtent: 120,//必传
childAspectRatio: 0.8, //宽高比例
),
itemCount: listData.length,
itemBuilder: _initThreeList);
}
}

动态渲染示例1
// 示例
class allPage extends StatelessWidget {
const allPage({super.key});
// 循环数组1
List<Widget> _initList() {
List<Widget> tempList = [];
for (var i = 0; i < 12; i++) {
tempList.add(Container(
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.blue),
child: Text(
"${i}元素",
style: TextStyle(fontSize: 20),
),
));
}
return tempList;
}
@override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: 3,
crossAxisSpacing: 20, //水平widget之间间距
mainAxisSpacing: 20, //垂直widget之间间距
padding: EdgeInsets.all(10),
childAspectRatio: 0.6, //宽高比例
children: _initList());
}
}

动态渲染示例2
// 示例
class allPage extends StatelessWidget {
const allPage({super.key});
//数组2
List<Widget> _initGridList() {
List listData = [
{"title": "one", "img": "http://tian-ji.xxxx.cn:9999/uploads/82.png"},
{"title": "two", "img": "http://tian-ji.xxxx.cn:9999/uploads/82.png"},
{"title": "three", "img": "http://tian-ji.xxxx.cn:9999/uploads/82.png"}
];
//循环数组2
var tempList2 = listData.map((value) {
return Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: const Color.fromARGB(255, 44, 145, 133), border: Border.all(color: Colors.black12)),
child: Column(
children: [
Image.network(value["img"]),
const SizedBox(height: 10),
Text(
value["title"],
style: TextStyle(fontSize: 18),
)
],
));
});
// tempList2返回的类似(1,2,4)
return tempList2.toList();
}
@override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: 3,
crossAxisSpacing: 20, //水平widget之间间距
mainAxisSpacing: 20, //垂直widget之间间距
padding: EdgeInsets.all(10),
childAspectRatio: 0.6, //宽高比例
children: _initGridList());
}
}

弹性布局(Flex Expanded)
- flex组件可以沿着水平或垂直方向排列子组件,如果你知道主轴方向,使用row或column会方便
- row和column都继承flex,参数基本相同

class Flexpage extends StatelessWidget {
const Flexpage({super.key});
@override
Widget build(BuildContext context) {
return Flex(
// 水平还是垂直
direction: Axis.horizontal,
// Expanded 主要用于在 Row、Column 或 Flex 等布局组件中按比例分配剩余空间
children: [
Expanded(flex: 1, child: Icon(Icons.pedal_bike)),
Expanded(flex: 2, child: Icon(Icons.pedal_bike))
]);
}
}
// 示例
class Flexallpage extends StatelessWidget {
const Flexallpage({super.key});
@override
Widget build(BuildContext context) {
return ListView(
children: [
Container(
width: double.infinity,
height: 200,
color: Colors.black,
),
const SizedBox(height: 5),
Row(
children: [
Expanded(
flex: 2,
child: Container(
height: 180,
color: Colors.amber,
child: Image.network(
'http://tian-ji.sunyay.cn:9999/uploads/82.png',
fit: BoxFit.cover,
),
)),
Expanded(
flex: 1,
child: Container(
height: 180,
color: Colors.red[200],
child: Column(
children: [
Expanded(
flex: 1,
child: SizedBox(
width: double.infinity,
child: Image.network(
'http://tian-ji.xxxx.cn:9999/uploads/my.png',
fit: BoxFit.cover,
),
)),
const SizedBox(height: 5),
Expanded(
flex: 1,
child: Image.network(
'http://tian-ji.xxxx.cn:9999/uploads/my.png',
fit: BoxFit.cover,
)),
],
),
))
],
)
],
);
}
}
Stack层叠组件,Stack和Positioned定位布局
- 获取宽高的另一种方法
// 获取设备的宽高
final size = MediaQuery.of(context).size;


import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "万物互联",
theme: ThemeData(
primaryColor: Colors.blue,
),
home: Scaffold(
appBar: AppBar(title: const Text('网格系统')), body: Stackallpage()),
);
}
}
//stack层叠布局
class Stackpage extends StatelessWidget {
const Stackpage({super.key});
@override
Widget build(BuildContext context) {
// alignment是相当于外层的层叠位置
return Stack(
alignment: Alignment.center,
children: [
Container(
height: 200,
width: 200,
color: Colors.red,
),
Container(
height: 100,
width: 100,
color: Colors.yellow,
),
Text('乞力马扎罗'),
],
);
}
}
class Stackallpage extends StatelessWidget {
const Stackallpage({super.key});
@override
Widget build(BuildContext context) {
// 获取设备的宽高
final size = MediaQuery.of(context).size;
// alignment是相当于外层的层叠位置
return Container(
height: double.infinity,
width: double.infinity,
color: Colors.red,
child: Stack(
children: [
ListView(
//上边距
padding: const EdgeInsets.only(top: 50),
children: [
ListTile(title: Text('数据列表0')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
ListTile(title: Text('数据列表1')),
],
),
Row(children: [
Expanded(
flex: 1,
child: Container(
alignment: Alignment.center,
height: 44,
color: Colors.amber[100],
child: Text('tab1'),
)),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.center,
height: 44,
color: Colors.amber[100],
child: Text('tab2'),
))
]),
// Positioned定位必须要有宽高
Positioned(
left: 0,
bottom: 0,
width: size.width,
height: 80,
// height: size.height,
child: Container(
height: 100,
width: 100,
color: Colors.yellow,
),
),
],
));
}
}
Stack与Align组合
- Align组件可以调整子组件的位置
- Stack组件中结合Align组件可以控制每个子元素的显示位置

class StackAlignAllpage extends StatelessWidget {
const StackAlignAllpage({super.key});
@override
Widget build(BuildContext context) {
return Column(
//不生效
// children: [
// Align(
// alignment: Alignment.topLeft,
// child: Text("订单管理"),
// ),
// Align(
// alignment: Alignment.topLeft,
// child: Text("个人首页"),
// )
// ],
//生效
children: [
Container(
width: double.infinity,
height: 40,
child: Stack(
children: [
Align(
alignment: Alignment.topLeft,
child: Text("订单管理"),
),
Align(
alignment: Alignment.topRight,
child: Text("个人首页"),
)
],
),
),
SizedBox(
width: double.infinity,
height: 40,
child: Stack(
children: [
Align(
alignment: Alignment.topLeft,
child: Text("订单管理"),
),
Align(
alignment: Alignment.topRight,
child: Text("个人首页"),
)
],
),
),
SizedBox(
//SizedBox作为容器给Positioned指定宽高
width: double.infinity,
height: 40,
child: Stack(
children: [
Positioned(
left: 10,
child: Text("订单管理"),
),
Positioned(
right: 10,
child: Text("个人首页"),
)
],
),
),
]);
}
}
AspectRatio组件 Card CircleAvatar组件
- AspectRatio的作用是调整子元素child的宽高比
//AspectRatio调整子元素宽高比
class AspectRatiopage extends StatelessWidget {
const AspectRatiopage({super.key});
@override
Widget build(BuildContext context) {
//设置宽高比2:1
return AspectRatio(
aspectRatio: 2 / 1,
child: Container(
color: Colors.red[100],
),
);
}
}
Card 组件
- 卡片组件块,具有圆角和阴影


// 卡片组件
class Cardpage extends StatelessWidget {
const Cardpage({super.key});
@override
Widget build(BuildContext context) {
return ListView(
children: [
Card(
//阴影
elevation: 10,
//颜色
color: Colors.amber[100],
//边距
margin: EdgeInsets.all(24),
//圆角
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
child: Column(
children: [
ListTile(
title: Text(
'一级标题',
style: TextStyle(fontSize: 28),
),
subtitle: Text('二级标题'),
),
Divider(),
ListTile(
title: Text(
'一级标题',
style: TextStyle(fontSize: 28),
),
subtitle: Text('二级标题'),
),
],
),
)
],
);
}
}
//卡片示例
class CardAllpage extends StatelessWidget {
const CardAllpage({super.key});
@override
Widget build(BuildContext context) {
return ListView(
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
margin: EdgeInsets.all(24),
child: Column(
children: [
AspectRatio(
aspectRatio: 16 / 9,
child: Image.network(
'http://tian-ji.sunyay.cn:9999/uploads/my.png',
fit: BoxFit.cover)),
ListTile(
leading: ClipOval(
child: Image.network(
'http://tian-ji.sunyay.cn:9999/uploads/my.png',
fit: BoxFit.cover,
width: 40,
height: 40,
),
),
title: Text('一级标题'),
subtitle: Text('副标题'),
)
],
),
),
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
margin: EdgeInsets.all(24),
child: Column(
children: [
AspectRatio(
aspectRatio: 16 / 9,
child: Image.network(
'http://tian-ji.sunyay.cn:9999/uploads/my.png',
fit: BoxFit.cover)),
ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: NetworkImage(
('http://tian-ji.sunyay.cn:9999/uploads/my.png'))),
title: Text('一级标题'),
subtitle: Text('副标题'),
)
],
),
)
],
);
}
}
圆形头像组件
- 方式1
ListTile(
leading: ClipOval(
child: Image.network(
'http://tian-ji.sunyay.cn:9999/uploads/my.png',
fit: BoxFit.cover,
width: 40,
height: 40,
),
),
title: Text('一级标题'),
subtitle: Text('副标题'),
)
- 方式2
- CircleAvatar不提供边框的属性
- 如果非要实现边框,可以将其包裹在更大的CircleAvatar中
ListTile(
leading: CircleAvatar(
radius: 20,
backgroundImage: NetworkImage(
('http://tian-ji.sunyay.cn:9999/uploads/my.png'))),
title: Text('一级标题'),
subtitle: Text('副标题'),
)
Wrap布局组件
- Wrap可以实现流布局,单行的Wrap和Row一样,单列的wrap和colum一样
- 但Row和colum是单行单列的
- Wrap突破了这个限制,mainAxis上空间不足的时候,则向crossAxis上扩展显示


//布局组件
class Button extends StatelessWidget {
String text; //按钮文字
void Function()? onPressed; //按钮方法
Button(this.text, {super.key, required this.onPressed});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
child: Text(text),
style: ButtonStyle(
backgroundColor:
WidgetStateProperty.all(Color.fromARGB(244, 255, 244, 244)),
foregroundColor: WidgetStateProperty.all(Colors.black45),
),
);
}
}
class WrapPage extends StatelessWidget {
const WrapPage({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(20),
child: ListView(
children: [
Row(
children: [
Text('热搜', style: Theme.of(context).textTheme.titleLarge)
],
),
const Divider(),
Wrap(
alignment: WrapAlignment.start,
spacing: 10, //主轴间距
runSpacing: 10, //垂直间距
// direction: Axis.vertical,
children: [
Button(
'第1集',
onPressed: () {
print('Button Clicked');
},
),
Button(
'第2集',
onPressed: () {
print('Button Clicked');
},
),
Button(
'第3集',
onPressed: () {
print('Button Clicked');
},
),
Button(
'第4集',
onPressed: () {
print('Button Clicked');
},
),
Button(
'第5集',
onPressed: () {
print('Button Clicked');
},
),
Button(
'第6集',
onPressed: () {
print('Button Clicked');
},
),
],
),
SizedBox(
height: 10,
),
Row(
children: [
Text('历史记录', style: Theme.of(context).textTheme.titleLarge)
],
),
Column(
children: [
ListTile(title: const Text("搜索记录1")),
Divider(),
ListTile(title: const Text("搜索记录2")),
],
),
SizedBox(
height: 40,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
OutlinedButton.icon(
style: ButtonStyle(
foregroundColor: WidgetStateProperty.all(Colors.black45)
),
onPressed: () {},
icon: Icon(Icons.delete),
label: Text('删除所有的历史记录')),
],
)
],
));
}
}
flutter动画详解
- photo_view预览动画
- 使图像能够通过用户手势(例如捏合,旋转,和拖动)进行缩放和平移
- 第三方插件地址:https:pub.dev/packages/photo_view
步骤1,pubspec.yaml文件导入
- dev_dependencies下 photo_view: ^0.15.0

单张图片查看
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
class HeroImage extends StatefulWidget {
final Map arguments;
const HeroImage({super.key, required this.arguments});
@override
State<HeroImage> createState() => _HeroImageState();
}
//单张图片预览
class _HeroImageState extends State<HeroImage> {
@override
Widget build(BuildContext context) {
return Scaffold(
// InkWell增加点击事件,点击空白出关闭预览图片
body: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Hero(
tag: widget.arguments['picurl'],
child: PhotoView(
imageProvider: NetworkImage(widget.arguments['picurl']),
)),
));
}
}
更多推荐

所有评论(0)