Flutter占位符加载插件skeletons的使用
Flutter占位符加载插件skeletons的使用
skeletons
是一个用于在加载页面时创建自定义骨架小部件的 Flutter 包。这些骨架小部件可以模仿页面布局,使用户在数据加载过程中也能看到页面结构。
示例
以下是几个使用 skeletons
插件的不同场景的示例图:
ListView (Default) | ListView (Custom) | ListView (Complex Cards) |
---|---|---|
![]() |
![]() |
![]() |
SkeletonTheme | Light/Dark modes | Right-To-Left |
---|---|---|
![]() |
![]() |
![]() |
Custom Shimmer | Paragraph | Items |
---|---|---|
![]() |
![]() |
![]() |
所有示例可以在 这里 查看。
如何使用
可以将子小部件封装在一个 Skeleton
小部件中使用:
import 'package:skeletons/skeletons.dart';
Skeleton(
isLoading: _isLoading,
skeleton: SkeletonListView(),
child: Container(
child: Center(
child: Text("Content"),
),
),
)
或者直接使用:
Container(
child: _isLoading
? SkeletonListView()
: Container(
child: Center(
child: Text("Content"),
),
),
)
还可以使用 SkeletonTheme
来设置树中所有骨架后代的默认配置:
SkeletonTheme(
// themeMode: ThemeMode.light,
shimmerGradient: LinearGradient(
colors: [
Color(0xFFD8E3E7),
Color(0xFFC8D5DA),
Color(0xFFD8E3E7),
],
stops: [
0.1,
0.5,
0.9,
],
),
darkShimmerGradient: LinearGradient(
colors: [
Color(0xFF222222),
Color(0xFF242424),
Color(0xFF2B2B2B),
Color(0xFF242424),
Color(0xFF222222),
],
stops: [
0.0,
0.2,
0.5,
0.8,
1,
],
begin: Alignment(-2.4, -0.2),
end: Alignment(2.4, 0.2),
tileMode: TileMode.clamp,
),
child: MaterialApp(
// 应用程序的主题和其他配置
),
)
更多定制化
对于更复杂的形状,可以使用 SkeletonItem
小部件来构建你的骨架:
ListView.builder(
physics: NeverScrollableScrollPhysics(),
itemCount: 5,
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(color: Colors.white),
child: SkeletonItem(
child: Column(
children: [
Row(
children: [
SkeletonAvatar(
style: SkeletonAvatarStyle(
shape: BoxShape.circle,
width: 50,
height: 50,
),
),
SizedBox(width: 8),
Expanded(
child: SkeletonParagraph(
style: SkeletonParagraphStyle(
lines: 3,
spacing: 6,
lineStyle: SkeletonLineStyle(
randomLength: true,
height: 10,
borderRadius: BorderRadius.circular(8),
minLength: MediaQuery.of(context).size.width / 6,
maxLength: MediaQuery.of(context).size.width / 3,
),
),
),
)
],
),
SizedBox(height: 12),
SkeletonParagraph(
style: SkeletonParagraphStyle(
lines: 3,
spacing: 6,
lineStyle: SkeletonLineStyle(
randomLength: true,
height: 10,
borderRadius: BorderRadius.circular(8),
minLength: MediaQuery.of(context).size.width / 2,
),
),
),
SizedBox(height: 12),
SkeletonAvatar(
style: SkeletonAvatarStyle(
width: double.infinity,
minHeight: MediaQuery.of(context).size.height / 8,
maxHeight: MediaQuery.of(context).size.height / 3,
),
),
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
SizedBox(width: 8),
SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
SizedBox(width: 8),
SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
],
),
SkeletonLine(
style: SkeletonLineStyle(
height: 16,
width: 64,
borderRadius: BorderRadius.circular(8),
),
)
],
)
],
),
),
),
),
);
问题与反馈
如果有任何问题,请在这里报告:GitHub Issues。欢迎贡献代码。
完整示例代码
下面是完整的示例代码,展示了如何在应用中使用 skeletons
插件:
import 'package:flutter/material.dart';
import 'package:skeletons/skeletons.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return SkeletonTheme(
shimmerGradient: LinearGradient(
colors: [
Color(0xFFD8E3E7),
Color(0xFFC8D5DA),
Color(0xFFD8E3E7),
],
stops: [
0.1,
0.5,
0.9,
],
),
darkShimmerGradient: LinearGradient(
colors: [
Color(0xFF222222),
Color(0xFF242424),
Color(0xFF2B2B2B),
Color(0xFF242424),
Color(0xFF222222),
],
stops: [
0.0,
0.2,
0.5,
0.8,
1,
],
begin: Alignment(-2.4, -0.2),
end: Alignment(2.4, 0.2),
tileMode: TileMode.clamp,
),
child: MaterialApp(
title: 'Skeletons Package Examples',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
),
);
}
}
class HomePage extends StatefulWidget {
[@override](/user/override)
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isLoading = true;
[@override](/user/override)
void initState() {
super.initState();
// 模拟异步加载数据
Future.delayed(Duration(seconds: 3), () {
setState(() {
_isLoading = false;
});
});
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Skeletons Example'),
),
body: _isLoading
? SkeletonListView()
: ListView.builder(
itemCount: 5,
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(color: Colors.white),
child: Column(
children: [
Row(
children: [
SkeletonAvatar(
style: SkeletonAvatarStyle(
shape: BoxShape.circle,
width: 50,
height: 50,
),
),
SizedBox(width: 8),
Expanded(
child: SkeletonParagraph(
style: SkeletonParagraphStyle(
lines: 3,
spacing: 6,
lineStyle: SkeletonLineStyle(
randomLength: true,
height: 10,
borderRadius: BorderRadius.circular(8),
minLength: MediaQuery.of(context).size.width / 6,
maxLength: MediaQuery.of(context).size.width / 3,
),
),
),
)
],
),
SizedBox(height: 12),
SkeletonParagraph(
style: SkeletonParagraphStyle(
lines: 3,
spacing: 6,
lineStyle: SkeletonLineStyle(
randomLength: true,
height: 10,
borderRadius: BorderRadius.circular(8),
minLength: MediaQuery.of(context).size.width / 2,
),
),
),
SizedBox(height: 12),
SkeletonAvatar(
style: SkeletonAvatarStyle(
width: double.infinity,
minHeight: MediaQuery.of(context).size.height / 8,
maxHeight: MediaQuery.of(context).size.height / 3,
),
),
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
SizedBox(width: 8),
SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
SizedBox(width: 8),
SkeletonAvatar(style: SkeletonAvatarStyle(width: 20, height: 20)),
],
),
SkeletonLine(
style: SkeletonLineStyle(
height: 16,
width: 64,
borderRadius: BorderRadius.circular(8),
),
)
],
)
],
),
),
),
),
);
}
}
更多关于Flutter占位符加载插件skeletons的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter占位符加载插件skeletons的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用占位符加载插件 skeletons
的代码案例。我们将通过安装和配置 flutter_skeleton_screen
这个流行的库来展示如何使用占位符(skeletons)来增强用户体验,尤其是在等待数据加载时。
1. 添加依赖
首先,在你的 pubspec.yaml
文件中添加 flutter_skeleton_screen
依赖:
dependencies:
flutter:
sdk: flutter
flutter_skeleton_screen: ^1.2.0 # 确保使用最新版本
2. 安装依赖
保存 pubspec.yaml
文件后,在终端运行以下命令来安装依赖:
flutter pub get
3. 使用 Skeletons
接下来,在你的 Flutter 应用中使用 SkeletonScreen
和 SkeletonWidget
来创建占位符。以下是一个完整的示例,展示如何在数据加载时显示占位符:
import 'package:flutter/material.dart';
import 'package:flutter_skeleton_screen/flutter_skeleton_screen.dart';
import 'package:flutter_skeleton_screen/skeleton_widget.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Skeletons Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Skeletons Example'),
),
body: MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool isLoading = true; // 模拟数据加载状态
List<String> data = []; // 模拟数据
@override
void initState() {
super.initState();
// 模拟异步数据加载
Future.delayed(Duration(seconds: 2), () {
setState(() {
isLoading = false;
data = List.generate(10, (index) => "Item ${index + 1}");
});
});
}
@override
Widget build(BuildContext context) {
return isLoading
? SkeletonScreen(
containerColor: Colors.grey[200]!,
skeletonChild: ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return SkeletonWidget.builder(
builder: (context, width, height) => ListTile(
leading: Icon(Icons.account_circle),
title: Text('Loading...'),
),
width: MediaQuery.of(context).size.width,
height: 50,
duration: Duration(milliseconds: 800),
count: 1,
enablePulseAnimation: true,
)[0];
},
),
)
: ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.account_circle),
title: Text(data[index]),
);
});
}
}
代码解释
- 依赖安装:我们在
pubspec.yaml
中添加了flutter_skeleton_screen
依赖,并运行flutter pub get
安装它。 - Skeletons 配置:在
MyHomePage
中,我们使用SkeletonScreen
来显示占位符,当数据加载时 (isLoading == true
)。 - 数据加载模拟:在
initState
中,我们使用Future.delayed
模拟异步数据加载,2秒后更新状态并填充数据。 - 占位符构建:使用
SkeletonWidget.builder
构建占位符,每个占位符的宽度和高度可以根据需要调整。这里我们为每个列表项生成了一个简单的占位符。 - 数据展示:一旦数据加载完成 (
isLoading == false
),我们使用ListView.builder
显示实际数据。
这个示例展示了如何在Flutter中使用 flutter_skeleton_screen
插件来增强用户体验,通过占位符在数据加载时给用户一个直观的反馈。