flutter 非常用组件整理 第三篇
视频
https://youtu.be/C5JnGxppJT8
https://www.bilibili.com/video/BV1XS411c7Rj/
前言
原文 https://ducafecat.com/blog/lesser-known-flutter-widgets-03
本文是非常用组件的第三讲,介绍了一些不为人知但却能大幅提升Flutter应用UI效果和功能的高级组件,包括FadeInImage、GridPaper、Hero等,为开发者带来更丰富的UI设计可能。
Flutter, 组件, UI开发, 高级组件, FadeInImage, GridPaper, Hero
参考
https://docs.flutter.dev/
正文
FadeInImage
FadeInImage 组件用于在加载图片时实现淡入效果,它可以在网络图片或资源图片加载过程中显示一个占位图,并在图片加载完成后淡入显示。这样可以提高用户体验,避免出现图片加载时的空白区域。下面是一个简单的例子:
Widget _mainView() {
return const FadeInImage(
placeholder: AssetImage('assets/app_icon.png'), // 占位图
image: NetworkImage(
'https://ducafecat.oss-cn-beijing.aliyuncs.com/podcast/2024/07/8f08bba2bf28bc26c38394cf5591b29d.png'), // 目标图片
fadeInDuration: Duration(milliseconds: 300), // 淡入时长
fadeInCurve: Curves.easeIn, // 淡入曲线
fit: BoxFit.cover, // 图片填充方式
);
}
在这个例子中:
placeholder
属性指定了占位图,这里使用了一个 logo png 图片。image
属性指定了目标图片,这里使用了一个网络图片。fadeInDuration
属性指定了淡入持续时间,这里设置为 300 毫秒。fadeInCurve
属性指定了淡入曲线,这里使用了Curves.easeIn
缓慢淡入的效果。fit
属性指定了图片的填充方式,这里使用了BoxFit.cover
将图片填充满整个容器。
当这段代码运行时,在目标图片加载完成之前,会先显示占位图并淡入,提供良好的用户体验。您可以根据实际需求调整各个属性的值。
FadeInImage 组件除了可以用于网络图片,也可以用于本地资源图片。如果您需要在图片加载过程中显示其他类型的占位控件,也可以使用 placeholder
属性来指定。总之,FadeInImage 是一个非常实用的 Flutter 组件,可以帮助您轻松实现图片的淡入效果。
GridPaper
GridPaper 是一个用于在 Flutter 应用程序中显示网格纸的小部件。它可以用于创建具有网格线的背景,以帮助设计和布局界面。下面是一个简单的例子:
Widget _mainView() {
return GridPaper(
color: Colors.grey, // 网格线颜色
divisions: 8, // 每个单元格分为8个小格
subdivisions: 1, // 每个小格子再细分1次
child: Container(
color: Colors.white, // 背景颜色
// 在网格纸上放置其他小部件
child: const Center(
child: Text('GridPaper Example'),
),
),
);
}
在这个例子中:
color
属性指定了网格线的颜色,这里使用了一种浅灰色。divisions
属性指定了每个单元格被分成多少个小格子,这里设置为 8。subdivisions
属性指定了每个小格子被细分为多少次,这里设置为 1。child
属性指定了要在网格纸上放置的其他小部件,这里是一个居中的文本。
当这段代码运行时,您将看到一个白色背景上有灰色网格线的 UI 元素。网格线可以帮助您快速定位和对齐页面上的其他小部件。
除了上述属性,GridPaper 还提供了其他一些属性,如 crossAxisCount
、mainAxisCount
和 subdivisionCount
。您可以根据实际需求调整这些属性,以创建更复杂的网格纸样式。
Hero
Hero 组件用于在页面之间实现平滑的过渡动画,通常用于实现点击图片放大的效果。当用户点击一个带有 Hero 组件的图片时,该图片会平滑地放大并过渡到新页面。下面是一个简单的例子:
主界面
Widget _mainView() {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const DetailPage()),
);
},
child: Hero(
tag: 'imageHero', // 必须在多个页面使用同样的tag
child: Center(
child: SizedBox(
width: 200,
child: Image.network(
'https://ducafecat.oss-cn-beijing.aliyuncs.com/podcast/2024/07/8f08bba2bf28bc26c38394cf5591b29d.png'),
),
),
),
);
}
详情页
class DetailPage extends StatelessWidget {
const DetailPage({
super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Detail')),
body: Center(
child: Hero(
tag: 'imageHero',
child: Image.network(
'https://ducafecat.oss-cn-beijing.aliyuncs.com/podcast/2024/07/8f08bba2bf28bc26c38394cf5591b29d.png'),
),
),
);
}
}
当点击小图后,会动画切入详情页图片。
在这个例子中:
- 主页面有一个
GestureDetector
包裹的Hero
组件,用于监听图片的点击事件。 tag
属性指定了这个 Hero 组件的标识,在多个页面中必须使用相同的 tag。- 当用户点击图片时,Navigator 会推入一个新的
DetailPage
页面,该页面也包含一个相同 tag 的Hero
组件。 - 在页面切换过程中,Flutter 会自动执行图片的放大过渡动画。
这样就实现了从主页面到详情页面的图片平滑过渡效果。Hero 组件不仅可以用于图片,也可以用于其他类型的 UI 元素,如文本、图标等。只要在多个页面中使用相同的 tag,Flutter 就会自动处理这些元素之间的过渡动画。
通过使用 Hero 组件,您可以轻松为应用程序添加丰富的过渡动画效果,提升用户体验。您还可以结合其他 Flutter 动画相关的组件,进一步优化动画效果。
KeepAlive
KeepAlive 组件用于保持子组件的状态,防止其在不可见时被销毁。这在某些场景下非常有用,比如当用户在应用程序中滚动到不同的页面时,我们希望之前的页面状态能够保留下来。
class _ChatPageState extends State<ChatPage>
with AutomaticKeepAliveClientMixin {
bool get wantKeepAlive => true;
Widget build(BuildContext context) {
super.build(context);
return _ChatViewGetX();
}
}
- 混入 AutomaticKeepAliveClientMixin
- 重写 wantKeepAlive => true
ListBody
ListBody 是一个用于创建垂直或水平排列的子组件列表的 Widget。它通常用于在 ListView 或 Column/Row 中作为子组件使用,用于管理子组件的布局和滚动行为。
下面是一个简单的示例:
Widget _mainView() {
return Column(
children: [
ListBody(
mainAxis: Axis.vertical,
children: [
Container(
color: Colors.blue,
height: 100,
child: const