Flutter生成趣味头像插件flutter_boring_avatars的使用
Flutter生成趣味头像插件flutter_boring_avatars的使用
Features
flutter_boring_avatars
可以基于用户名和颜色调色板生成独特的头像。该项目是 Boring Avatars 的Flutter实现,使用Canvas进行渲染,并添加了过渡动画。
你可以通过 Web Demo 体验效果。
Installation
在你的 pubspec.yaml
文件中添加依赖:
dependencies:
flutter_boring_avatars: any # 或者使用 Pub 上的最新版本
Usage
获取简单头像
BoringAvatar(name: "Maria Mitchell", type: BoringAvatarType.marble);
获取带有过渡动画的头像
AnimatedBoringAvatar(
name: "Maria Mitchell",
type: BoringAvatarType.marble,
duration: const Duration(milliseconds: 300),
)
自定义颜色调色板
final colorPalette = BoringAvatarPalette(Color(0xffA3A948), Color(0xffEDB92E), Color(0xffF85931), Color(0xffCE1836), Color(0xff009989));
BoringAvatar(name: "Maria Mitchell", palette: colorPalette);
设置默认类型和调色板
build(context) {
return DefaultBoringAvatarStyle(
type: BoringAvatarType.marble,
palette: colorPalette,
child: Column(
children: [
BoringAvatar(name: "Maria Mitchell"),
BoringAvatar(name: "Alexis Brooks"),
BoringAvatar(name: "Justin Gray"),
]
),
);
}
使用ShapeBorder控制头像形状并添加边框
BoringAvatar(
name: "Maria Mitchell",
type: BoringAvatarType.marble,
shape: OvalBorder(), // 或者使用 RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))
);
作为装饰使用头像,支持在AnimatedContainer中的过渡动画
Container(
decoration: BoringAvatarDecoration(
avatarData: BoringAvatarData.generate(name: name),
),
);
导出头像为图片
final avatarData = BoringAvatarData.generate(name: name);
final image = await avatarData.toImage(size: const Size.square(256));
final pngByteData = await image.toByteData(format: ImageByteFormat.png);
示例代码
下面是一个完整的示例应用,展示了如何使用 flutter_boring_avatars
插件创建一个可以交互的头像生成器。
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_boring_avatars/flutter_boring_avatars.dart';
void main() {
runApp(const MaterialApp(home: MyApp()));
}
class AvatarInputWidget extends StatefulWidget {
const AvatarInputWidget({
Key? key,
required this.name,
required this.onNameChanged,
required this.resetInput,
required this.shape,
}) : super(key: key);
final String name;
final ValueChanged<String> onNameChanged;
final int resetInput;
final ShapeBorder shape;
@override
State<AvatarInputWidget> createState() => _AvatarInputWidgetState();
}
class _AvatarInputWidgetState extends State<AvatarInputWidget> {
late TextEditingController textController = TextEditingController(
text: widget.name,
);
late int inputKey = widget.resetInput;
copyImage() async {
final type = DefaultBoringAvatarType.maybeOf(context)?.type ??
BoringAvatarType.marble;
final colorPalette = DefaultBoringAvatarPalette.maybeOf(context)?.palette ??
BoringAvatarPalette.defaultPalette;
final image = await BoringAvatarData.generate(
name: widget.name,
type: type,
palette: colorPalette,
// shape: widget.shape,
).toImage(
size: const Size.square(512),
);
final pngData = await image.toByteData(format: ImageByteFormat.png);
final clipboard = SystemClipboard.instance;
if (clipboard == null) {
return; // Clipboard API is not supported on this platform.
}
final item = DataWriterItem();
item.add(Formats.png(pngData!.buffer.asUint8List()));
await clipboard.write([item]);
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Avatar image copied to clipboard'),
),
);
}
@override
Widget build(BuildContext context) {
if (widget.resetInput != inputKey) {
textController = TextEditingController(
text: widget.name,
);
inputKey = widget.resetInput;
}
return Column(
children: [
Expanded(
child: AnimatedBoringAvatar(
duration: const Duration(milliseconds: 1200),
curve: Curves.easeInOutCubicEmphasized,
name: widget.name,
shape: widget.shape,
child: RawMaterialButton(
shape: widget.shape,
onPressed: copyImage,
),
),
),
const SizedBox(height: 8),
SizedBox(
height: 24,
child: TextField(
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 1),
borderRadius: BorderRadius.all(Radius.circular(32)),
),
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey.withOpacity(0.0), width: 1),
borderRadius: const BorderRadius.all(Radius.circular(32)),
),
),
controller: textController,
style: const TextStyle(fontSize: 12),
textAlign: TextAlign.center,
onChanged: widget.onNameChanged,
),
),
const SizedBox(height: 8),
],
);
}
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
String name = 'Bessie Coleman';
TextEditingController textController = TextEditingController.fromValue(
const TextEditingValue(text: 'Bessie Coleman'));
BoringAvatarType type = BoringAvatarType.beam;
RandomNames randomNames = RandomNames(Zone.us);
late BoringAvatarPalette colorPalette;
late List<String> names;
ShapeBorder shape = const OvalBorder();
@override
void initState() {
colorPalette = BoringAvatarPalette(getRandomColors());
names = List.generate(200, (index) => randomNames.fullName());
super.initState();
}
avatarItem(int index) {
final name = names[index];
return AvatarInputWidget(
name: name,
resetInput: names.hashCode,
shape: shape,
onNameChanged: (name) {
setState(() {
names[index] = name;
});
});
}
goToTestPage() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => TestPage()),
);
}
@override
Widget build(BuildContext context) {
final colorScheme =
ColorScheme.fromSeed(seedColor: colorPalette.getColor(2));
return MaterialApp(
theme: ThemeData.from(colorScheme: colorScheme),
home: Scaffold(
appBar: AppBar(
centerTitle: true,
title: GestureDetector(
child: Text('Boring Avatars'),
onTap: goToTestPage,
),
actions: [
IconButton(
tooltip: 'Pub.dev',
onPressed: () async {
final uri = Uri.parse(
'https://pub.dev/packages/flutter_boring_avatars');
if (!await launchUrl(uri, webOnlyWindowName: '_blank')) {
throw Exception('Could not launch $uri');
}
},
icon: const Icon(Icons.brand_flutter),
),
IconButton(
tooltip: 'Github',
onPressed: () async {
final uri = Uri.parse(
'https://github.com/xioxin/flutter_boring_avatars');
if (!await launchUrl(uri, webOnlyWindowName: '_blank')) {
throw Exception('Could not launch $uri');
}
},
icon: const Icon(Icons.brand_github),
),
IconButton(
tooltip: 'Randomize All',
onPressed: () {
setState(() {
names =
List.generate(2000, (index) => randomNames.fullName());
colorPalette = BoringAvatarPalette(getRandomColors());
});
},
icon: const Icon(Icons.refresh),
),
],
),
body: Stack(
children: [
DefaultBoringAvatarStyle(
type: type,
palette: colorPalette,
child: Positioned.fill(
child: GridView.builder(
padding: const EdgeInsets.only(
left: 32, top: 140, right: 32, bottom: 32),
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 140,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
),
itemCount: names.length,
itemBuilder: (context, index) {
return avatarItem(index);
},
),
),
),
Positioned(
top: 0,
left: 16,
right: 16,
child: ControlBarWidget(
type: type,
palette: colorPalette,
shape: shape,
onShapeChanged: (v) {
setState(() {
shape = v;
});
},
onTypeChanged: (v) {
setState(() {
type = v;
});
},
onPaletteChanged: (v) {
setState(() {
colorPalette = v;
});
},
onRandomizeNames: () {
setState(() {
names =
List.generate(2000, (index) => randomNames.fullName());
});
},
),
),
],
),
),
);
}
}
这个示例应用展示了如何使用 flutter_boring_avatars
创建一个可以自定义和导出的趣味头像生成器。你可以根据需要调整和扩展此代码以满足特定需求。
更多关于Flutter生成趣味头像插件flutter_boring_avatars的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter生成趣味头像插件flutter_boring_avatars的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用flutter_boring_avatars
插件来生成趣味头像的示例代码。这个插件允许你基于一些简单的参数生成有趣的、独一无二的头像。
首先,你需要在你的pubspec.yaml
文件中添加flutter_boring_avatars
依赖:
dependencies:
flutter:
sdk: flutter
flutter_boring_avatars: ^x.y.z # 替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来,在你的Dart文件中,你可以按照以下方式使用flutter_boring_avatars
:
import 'package:flutter/material.dart';
import 'package:flutter_boring_avatars/flutter_boring_avatars.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Boring Avatars Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 配置生成头像的参数
final avatarParams = BoringAvatarParams(
text: 'AB12', // 文本可以是任何字符串,用于生成头像的一部分
backgroundColor: Colors.grey[300]!, // 背景颜色
foregroundColor: Colors.blue, // 前景颜色(通常是文本颜色)
shape: BoringAvatarShape.circle, // 头像形状(圆形或方形)
borderRadius: 10.0, // 如果形状是方形,可以设置圆角半径
size: 100.0, // 头像大小
);
return Scaffold(
appBar: AppBar(
title: Text('Flutter Boring Avatars Demo'),
),
body: Center(
child: BoringAvatar(
params: avatarParams,
),
),
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个使用BoringAvatar
生成的趣味头像。BoringAvatarParams
类允许我们自定义头像的多个方面,包括文本、背景颜色、前景颜色、形状、圆角半径和大小。
你可以根据需要调整avatarParams
中的参数来生成不同的头像。text
参数通常是一个简短的字符串,它会被用来生成头像的一部分图案。
这个插件非常适合在需要快速生成独特头像的应用中使用,比如用户头像生成器、游戏角色创建工具等。