diff --git a/app/lib/features/editor/widgets/sticker_picker_sheet.dart b/app/lib/features/editor/widgets/sticker_picker_sheet.dart new file mode 100644 index 0000000..525a020 --- /dev/null +++ b/app/lib/features/editor/widgets/sticker_picker_sheet.dart @@ -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 = >{ + '心情': ['😊', '😢', '😡', '🤔', '😐', '🥰', '😋', '🤗', '😴', '🎉'], + '动物': ['🐱', '🐶', '🐰', '🐻', '🦊', '🐼', '🐨', '🦄', '🐸', '🦋'], + '自然': ['🌸', '🌺', '🌻', '🍀', '🌈', '⭐', '🌙', '☀️', '❄️', '🍃'], + '食物': ['🍰', '🍩', '🍦', '🍓', '🍎', '🧁', '🍪', '🍕', '🍔', '🥤'], + '学校': ['📚', '✏️', '🎨', '📝', '📐', '🎒', '🏆', '📖', '💡', '🔔'], + '装饰': ['💕', '✨', '🎀', '🎵', '🎶', '💫', '🦋', '🌸', '🍀', '💎'], + }; + + @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(), + ), + ), + ], + ), + ); + } +}