Flutter动态GIF展示对话框插件giffy_dialog的使用
Flutter动态GIF展示对话框插件giffy_dialog的使用
Giffy Dialog
Giffy Dialog
是一个受 FancyAlertDialog-Android 启发的Flutter库,用于创建带有动态GIF的自定义对话框。
显示一些❤️并为项目加星以支持它
在线演示: https://xsahil03x.github.io/giffy_dialog
从v1迁移到v2
请参考migration guide来了解如何从v1迁移到v2。
安装
在你的 pubspec.yaml
文件中添加以下内容,并将 [version]
替换为最新版本:
dependencies:
giffy_dialog: ^[version]
使用方法
导入包
import 'package:giffy_dialog/giffy_dialog.dart';
显示对话框
showDialog(
context: context,
builder: (BuildContext context) {
return GiffyDialog.image(
Image.network(
"https://raw.githubusercontent.com/Shashank02051997/FancyGifDialog-Android/master/GIF's/gif14.gif",
height: 200,
fit: BoxFit.cover,
),
title: Text(
'Image Animation',
textAlign: TextAlign.center,
),
content: Text(
'This is a image animation dialog box. This library helps you easily create fancy giffy dialog.',
textAlign: TextAlign.center,
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 'CANCEL'),
child: const Text('CANCEL'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
);
},
);
显示底部弹出窗口
showModalBottomSheet(
context: context,
clipBehavior: Clip.antiAlias,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(useMaterial3 ? 32 : 4),
),
),
builder: (BuildContext context) {
return GiffyBottomSheet.image(
Image.network(
"https://raw.githubusercontent.com/Shashank02051997/FancyGifDialog-Android/master/GIF's/gif14.gif",
height: 200,
fit: BoxFit.cover,
),
title: Text(
'Image Animation',
textAlign: TextAlign.center,
),
content: Text(
'This is a image animation bottom sheet. This library helps you easily create fancy giffy bottom sheet.',
textAlign: TextAlign.center,
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 'CANCEL'),
child: const Text('CANCEL'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
);
},
);
示例代码
以下是一个完整的示例代码,展示了如何使用 Giffy Dialog
和 Giffy BottomSheet
来创建不同类型的动画对话框和底部弹出窗口。
import 'package:flutter/material.dart';
import 'package:giffy_dialog/giffy_dialog.dart';
import 'package:google_fonts/google_fonts.dart';
void main() => runApp(MyApp());
final material3Notifier = ValueNotifier<bool>(true);
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<bool>(
valueListenable: material3Notifier,
builder: (context, useMaterial3, _) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Giffy Demo',
theme: ThemeData(
brightness: Brightness.light,
useMaterial3: useMaterial3,
colorSchemeSeed: Colors.teal,
textTheme: GoogleFonts.ralewayTextTheme(),
),
darkTheme: ThemeData(
brightness: Brightness.dark,
useMaterial3: useMaterial3,
colorSchemeSeed: Colors.teal,
textTheme: GoogleFonts.ralewayTextTheme(),
),
home: MyHomePage(),
);
},
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Giffy Example"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MaterialToggleButtons(),
SizedBox(height: 30),
Text('Image Giffy'),
SizedBox(height: 10),
TypedExample(type: GiffyType.image),
SizedBox(height: 30),
Text('Rive Giffy'),
SizedBox(height: 10),
TypedExample(type: GiffyType.rive),
SizedBox(height: 30),
Text('Lottie Giffy'),
SizedBox(height: 10),
TypedExample(type: GiffyType.lottie),
],
),
),
);
}
}
class MaterialToggleButtons extends StatelessWidget {
const MaterialToggleButtons({super.key});
@override
Widget build(BuildContext context) {
final useMaterial3 = Theme.of(context).useMaterial3;
final primary = Theme.of(context).colorScheme.primary;
final isDark = Theme.of(context).brightness == Brightness.dark;
final selectedColor = useMaterial3
? primary
: isDark
? Colors.black
: Colors.white;
final borderColor = useMaterial3 ? primary.withOpacity(0.12) : primary;
final borderRadius = useMaterial3
? const BorderRadius.all(Radius.circular(16))
: const BorderRadius.all(Radius.circular(4));
return ToggleButtons(
isSelected: [!useMaterial3, useMaterial3],
borderRadius: borderRadius,
borderColor: borderColor,
selectedBorderColor: borderColor,
color: primary,
selectedColor: selectedColor,
fillColor: borderColor,
constraints: const BoxConstraints(
minHeight: 30.0,
minWidth: 100.0,
),
onPressed: (index) {
material3Notifier.value = index == 1;
},
children: [Text('Material 2'), Text('Material 3')],
);
}
}
enum GiffyType {
image,
rive,
lottie;
Widget when({
required Widget Function() image,
required Widget Function() rive,
required Widget Function() lottie,
}) {
switch (this) {
case GiffyType.image:
return image();
case GiffyType.rive:
return rive();
case GiffyType.lottie:
return lottie();
}
}
}
class TypedExample extends StatelessWidget {
const TypedExample({
super.key,
required this.type,
});
final GiffyType type;
@override
Widget build(BuildContext context) {
final useMaterial3 = Theme.of(context).useMaterial3;
final image = GiffyModel.image(context);
final rive = GiffyModel.rive(context);
final lottie = GiffyModel.lottie(context);
Widget buildDialog() {
return type.when(
image: () {
return GiffyDialog.image(
image.giffy as Image,
title: image.title,
content: image.content,
actions: image.actions,
);
},
rive: () {
return GiffyDialog.rive(
rive.giffy as RiveAnimation,
giffyBuilder: (context, rive) {
return ClipRRect(
borderRadius: useMaterial3
? const BorderRadius.all(Radius.circular(16))
: const BorderRadius.all(Radius.circular(4)),
child: SizedBox(height: 200, child: rive),
);
},
title: rive.title,
content: rive.content,
actions: rive.actions,
);
},
lottie: () {
return GiffyDialog.lottie(
lottie.giffy as LottieBuilder,
title: lottie.title,
content: lottie.content,
actions: lottie.actions,
);
},
);
}
Widget buildBottomSheet() {
return type.when(
image: () {
return GiffyBottomSheet.image(
image.giffy as Image,
title: image.title,
content: image.content,
actions: image.actions,
);
},
rive: () {
return GiffyBottomSheet.rive(
rive.giffy as RiveAnimation,
giffyBuilder: (context, rive) {
return ClipRRect(
borderRadius: useMaterial3
? const BorderRadius.all(Radius.circular(16))
: const BorderRadius.all(Radius.circular(4)),
child: SizedBox(height: 200, child: rive),
);
},
title: rive.title,
content: rive.content,
actions: rive.actions,
);
},
lottie: () {
return GiffyBottomSheet.lottie(
lottie.giffy as LottieBuilder,
title: lottie.title,
content: lottie.content,
actions: lottie.actions,
);
},
);
}
return SizedBox(
height: 36,
child: Row(
children: [
Expanded(
child: ElevatedButton(
child: Text('Show Dialog'),
onPressed: () {
showDialog(
context: context,
builder: (_) {
return buildDialog();
},
);
},
),
),
VerticalDivider(),
Expanded(
child: ElevatedButton(
child: Text('Show Bottom Sheet'),
onPressed: () {
showModalBottomSheet(
context: context,
clipBehavior: Clip.antiAlias,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(useMaterial3 ? 32 : 4),
),
),
builder: (_) {
return buildBottomSheet();
},
);
},
),
),
],
),
);
}
}
class GiffyModel {
final Widget giffy;
final Widget title;
final Widget content;
final List<Widget> actions;
const GiffyModel({
required this.giffy,
required this.title,
required this.content,
required this.actions,
});
factory GiffyModel.image(BuildContext context) {
return GiffyModel(
giffy: Image.network(
"https://raw.githubusercontent.com/Shashank02051997/FancyGifDialog-Android/master/GIF's/gif14.gif",
height: 200,
fit: BoxFit.cover,
),
title: Text(
'Image Animation',
textAlign: TextAlign.center,
),
content: Text(
'This is a image animation dialog box. This library helps you easily create fancy giffy dialog.',
textAlign: TextAlign.center,
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 'CANCEL'),
child: const Text('CANCEL'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
);
}
factory GiffyModel.rive(BuildContext context) {
return GiffyModel(
giffy: RiveAnimation.network(
'https://cdn.rive.app/animations/vehicles.riv',
fit: BoxFit.cover,
placeHolder: Center(child: CircularProgressIndicator()),
),
title: Text(
'Rive Animation',
textAlign: TextAlign.center,
),
content: Text(
'This is a rive animation dialog box. This library helps you easily create fancy giffy dialog.',
textAlign: TextAlign.center,
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 'CANCEL'),
child: const Text('CANCEL'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
);
}
factory GiffyModel.lottie(BuildContext context) {
return GiffyModel(
giffy: Lottie.network(
'https://raw.githubusercontent.com/xvrh/lottie-flutter/master/example/assets/Mobilo/A.json',
fit: BoxFit.contain,
height: 200,
),
title: Text(
'Lottie Animation',
textAlign: TextAlign.center,
),
content: Text(
'This is a lottie animation dialog box. This library helps you easily create fancy giffy dialog.',
textAlign: TextAlign.center,
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, 'CANCEL'),
child: const Text('CANCEL'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
);
}
}
自定义选项
GiffyDialog
提供了多种自定义选项,例如对话框标题、描述、按钮、动画等。请参考 官方文档 获取更多信息。
贡献者
感谢所有贡献者,他们为这个项目做出了巨大贡献。
许可证
本项目遵循 MIT License。
希望这个帖子能帮助你更好地理解和使用 giffy_dialog
插件。如果你有任何问题或需要进一步的帮助,请随时提问!
更多关于Flutter动态GIF展示对话框插件giffy_dialog的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter动态GIF展示对话框插件giffy_dialog的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter中使用giffy_dialog
插件来展示动态GIF的示例代码。这个插件允许你轻松地在一个对话框中展示GIF图像。
首先,你需要在你的pubspec.yaml
文件中添加giffy_dialog
依赖:
dependencies:
flutter:
sdk: flutter
giffy_dialog: ^2.0.0 # 请检查最新版本号
然后运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter应用中使用GiffyDialog
来展示GIF。以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'package:giffy_dialog/giffy_dialog.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter GiffyDialog Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
final String gifUrl = 'https://example.com/path/to/your/gif.gif'; // 替换为你的GIF URL
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GiffyDialog Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: () => showGiffyDialog(context, gifUrl),
child: Text('Show GIF'),
),
),
);
}
void showGiffyDialog(BuildContext context, String gifUrl) {
GiffyDialog.builder(
context: context,
initialTitle: 'GIF Dialog',
image: NetworkImage(gifUrl),
description: 'This is a demo GIF',
onOkButtonClicked: () {
// 点击确定按钮后的回调
print('OK button clicked');
},
onCancelButtonClicked: () {
// 点击取消按钮后的回调
print('Cancel button clicked');
},
shouldDisposeWhenClose: true,
// 其他可选参数,如标题、描述、按钮文本等,可以根据需要配置
).show();
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮。点击按钮时,会调用showGiffyDialog
函数,该函数使用GiffyDialog.builder
来显示一个包含GIF的对话框。
请注意以下几点:
gifUrl
应该替换为你实际想要展示的GIF图像的URL。GiffyDialog.builder
提供了许多可选参数,如initialTitle
、description
、onOkButtonClicked
和onCancelButtonClicked
等,你可以根据需要进行配置。shouldDisposeWhenClose
参数决定对话框关闭后是否释放资源。
这个示例展示了如何使用giffy_dialog
插件在Flutter应用中展示动态GIF图像。希望这对你有所帮助!