petsHero-AI/lib/features/generate_video/widgets/album_picker_sheet.dart

165 lines
5.3 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/theme/app_spacing.dart';
/// [showModalBottomSheet] 返回此值时由**外层页面**调系统相机,避免 BottomSheet 与相机 Activity 叠放导致返回后黑屏/卡死。
const String kAlbumPickerRequestCamera = '__album_picker_camera__';
/// 由外层调用 [ImagePicker](系统照片选择器 / Photo Picker避免在 Sheet 内嵌套系统选图界面。
const String kAlbumPickerRequestGallery = '__album_picker_gallery__';
/// 底部弹层:拍照 与 从相册选择Android 使用系统照片选择器,不申请 READ_MEDIA_*
class AlbumPickerSheet extends StatelessWidget {
const AlbumPickerSheet({super.key});
@override
Widget build(BuildContext context) {
final bottomPad = MediaQuery.paddingOf(context).bottom;
return Material(
color: AppColors.surface,
borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
clipBehavior: Clip.antiAlias,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(
AppSpacing.sm,
AppSpacing.sm,
AppSpacing.sm,
AppSpacing.md,
),
child: Row(
children: [
IconButton(
onPressed: () => Navigator.of(context).pop<String?>(),
icon: const Icon(LucideIcons.x, color: AppColors.textPrimary),
),
const Expanded(
child: Text(
'Choose photo',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
),
),
),
const SizedBox(width: 48),
],
),
),
const Divider(height: 1, color: AppColors.border),
Padding(
padding: EdgeInsets.fromLTRB(
AppSpacing.lg,
AppSpacing.lg,
AppSpacing.lg,
AppSpacing.xl + bottomPad,
),
child: Column(
children: [
_ActionCard(
icon: LucideIcons.camera,
title: 'Take photo',
subtitle: 'Use camera',
onTap: () => Navigator.of(context)
.pop<String>(kAlbumPickerRequestCamera),
),
const SizedBox(height: AppSpacing.md),
_ActionCard(
icon: LucideIcons.images,
title: 'Choose from gallery',
subtitle: 'System photo picker',
onTap: () => Navigator.of(context)
.pop<String>(kAlbumPickerRequestGallery),
),
],
),
),
],
),
);
}
}
class _ActionCard extends StatelessWidget {
const _ActionCard({
required this.icon,
required this.title,
required this.subtitle,
required this.onTap,
});
final IconData icon;
final String title;
final String subtitle;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return Material(
color: AppColors.surfaceAlt,
borderRadius: BorderRadius.circular(14),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(14),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.lg,
vertical: AppSpacing.lg,
),
child: Row(
children: [
Container(
width: 52,
height: 52,
decoration: BoxDecoration(
color: AppColors.primary.withValues(alpha: 0.12),
borderRadius: BorderRadius.circular(12),
),
child: Icon(icon, size: 26, color: AppColors.primary),
),
const SizedBox(width: AppSpacing.lg),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.textPrimary,
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: TextStyle(
fontSize: 13,
height: 1.3,
color: AppColors.textSecondary.withValues(alpha: 0.95),
),
),
],
),
),
Icon(
LucideIcons.chevron_right,
size: 20,
color: AppColors.textSecondary.withValues(alpha: 0.7),
),
],
),
),
),
);
}
}