feat(app): 创建贴纸选择底部面板 — 6 类 60 个 emoji 贴纸

This commit is contained in:
iven
2026-06-01 21:36:51 +08:00
parent 89c1cefb11
commit 57b45f7cbf

View File

@@ -0,0 +1,97 @@
// 贴纸选择底部面板
//
// Phase 1 使用内置 emoji 贴纸6 类 60 个),后续替换为贴纸包资源。
// 分类:心情/动物/自然/食物/学校/装饰
import 'package:flutter/material.dart';
/// 贴纸选择底部面板
class StickerPickerSheet extends StatelessWidget {
final void Function(String emoji) onStickerSelected;
const StickerPickerSheet({
super.key,
required this.onStickerSelected,
});
// Phase 1 内置贴纸集
static const _stickerCategories = <String, List<String>>{
'心情': ['😊', '😢', '😡', '🤔', '😐', '🥰', '😋', '🤗', '😴', '🎉'],
'动物': ['🐱', '🐶', '🐰', '🐻', '🦊', '🐼', '🐨', '🦄', '🐸', '🦋'],
'自然': ['🌸', '🌺', '🌻', '🍀', '🌈', '', '🌙', '☀️', '❄️', '🍃'],
'食物': ['🍰', '🍩', '🍦', '🍓', '🍎', '🧁', '🍪', '🍕', '🍔', '🥤'],
'学校': ['📚', '✏️', '🎨', '📝', '📐', '🎒', '🏆', '📖', '💡', '🔔'],
'装饰': ['💕', '', '🎀', '🎵', '🎶', '💫', '🦋', '🌸', '🍀', '💎'],
};
@override
Widget build(BuildContext context) {
return Container(
height: 320,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: const BorderRadius.vertical(top: Radius.circular(22)),
),
child: Column(
children: [
// 拖拽条
Center(
child: Container(
margin: const EdgeInsets.symmetric(vertical: 8),
width: 40,
height: 4,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(2),
),
),
),
// 分类标签
SizedBox(
height: 40,
child: ListView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 16),
children: _stickerCategories.keys.map((category) {
return Padding(
padding: const EdgeInsets.only(right: 8),
child: Chip(
label: Text(category, style: const TextStyle(fontSize: 13)),
visualDensity: VisualDensity.compact,
),
);
}).toList(),
),
),
const Divider(height: 1),
// 贴纸网格
Expanded(
child: GridView.count(
crossAxisCount: 5,
padding: const EdgeInsets.all(16),
mainAxisSpacing: 8,
crossAxisSpacing: 8,
children: _stickerCategories.values
.expand((list) => list)
.map((emoji) {
return InkWell(
onTap: () {
onStickerSelected(emoji);
Navigator.pop(context);
},
borderRadius: BorderRadius.circular(8),
child: Center(
child: Text(
emoji,
style: const TextStyle(fontSize: 32),
),
),
);
}).toList(),
),
),
],
),
);
}
}