简介
一般表格的列表会提供一个空视图。然后在拉网络数据的时候,给一个loading表示数据传输状态。
在loading的时候,放空视图不是很好。但是又没有数据,所以很多时候会是空白视图,加一个loading。
这个过渡状态有时候1秒不到,有时候两三秒,也有时候七八秒,这个要看网络数据访问的状态。
图片加载过程会有一个占位图,那么网络访问的时候,就给整个页面给个占位页面。
并且这个时候在进行网络访问,所以一般会给个动画,表示在努力加载数据。
搜索插件
在pub.dev输入关键shimmer,发现有一个插件特别受欢迎。
这种优势很明显,不是特殊情况的话,就用这个就好了。
安装插件
flutter pub add shimmer
封装
占位图不能做到前端一样分步加载,只能重新写一个视图。
占位图大多数时候是一个矩形,少部分是一个圆形,所以可以封装成一个组件。
颜色的话用不同透明度的灰色比较好。
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
class ShimmerWidget extends StatelessWidget {
final double width;
final double height;
final ShapeBorder shapeBorder;
final Color baseColor;
final Color highlightColor;
const ShimmerWidget({
Key? key,
required this.width,
required this.height,
this.shapeBorder = const RoundedRectangleBorder(),
this.baseColor = const Color(0x80000000),
this.highlightColor = const Color(0x33000000),
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Shimmer.fromColors(
baseColor: baseColor,
highlightColor: highlightColor,
child: Container(
width: width,
height: height,
decoration: ShapeDecoration(
color: const Color(0x4D000000),
shape: shapeBorder,
),
),
);
}
}
使用
可以把这个自定义的ShimmerWidget组件当做SizedBox来使用。按照设计图给尺寸就行。
/// 闪烁视图
Widget _buildShimmer() {
return Container(
margin: EdgeInsets.symmetric(
horizontal: 10.w,
),
child: ListView.builder(
itemCount: 5,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.only(
top: 10.h,
),
padding: EdgeInsets.symmetric(
horizontal: 10.w,
vertical: 15.h,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(6.r),
boxShadow: const [
BoxShadow(
color: Color(0x0D000000),
offset: Offset(0.0, 1.0),
blurRadius: 5,
),
],
),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
ShimmerWidget(
width: 16.w,
height: 16.w,
),
SizedBox(
width: 5.w,
),
ShimmerWidget(
width: 200.w,
height: 16.h,
),
],
),
ShimmerWidget(
width: 80.w,
height: 16.h,
),
],
),
SizedBox(
height: 10.h,
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ShimmerWidget(
width: 80.w,
height: 80.w,
),
SizedBox(
width: 5.w,
),
Expanded(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ShimmerWidget(
width: 180.w,
height: 16.h,
),
ShimmerWidget(
width: 60.w,
height: 16.h,
),
],
),
SizedBox(
height: 5.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ShimmerWidget(
width: 180.w,
height: 16.h,
),
ShimmerWidget(
width: 12.w,
height: 16.h,
),
],
),
SizedBox(
height: 5.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ShimmerWidget(
width: 100.w,
height: 16.h,
),
ShimmerWidget(
width: 70.w,
height: 16.h,
),
],
),
SizedBox(
height: 5.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ShimmerWidget(
width: 80.w,
height: 16.h,
),
],
),
],
),
),
],
),
SizedBox(
height: 5.h,
),
const Divider(
color: Color(0xFFF2F2F2),
thickness: 0.5,
),
SizedBox(
height: 10.h,
),
ShimmerWidget(
width: double.infinity,
height: 20.h,
),
],
),
);
},
),
);
}
效果
参考文章
Flutter 中的 Shimmer 动画效果