354 lines
10 KiB
Dart
354 lines
10 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart' show rootBundle, ByteData;
|
|
import 'dart:ui' as ui;
|
|
import 'package:aesthetica_wallpaper/models/recipe.dart';
|
|
import 'wallpaper_preview_painter.dart';
|
|
|
|
// 全屏预览对话框
|
|
class FullScreenPreviewDialog extends StatefulWidget {
|
|
final Recipe recipe;
|
|
|
|
const FullScreenPreviewDialog({super.key, required this.recipe});
|
|
|
|
@override
|
|
State<FullScreenPreviewDialog> createState() =>
|
|
_FullScreenPreviewDialogState();
|
|
}
|
|
|
|
class _FullScreenPreviewDialogState extends State<FullScreenPreviewDialog> {
|
|
bool _isHomeScreen = true; // true = 主页, false = 锁屏
|
|
ui.Image? _loadedImage;
|
|
bool _isLoading = true;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadImage();
|
|
}
|
|
|
|
// 异步加载图片
|
|
Future<void> _loadImage() async {
|
|
try {
|
|
final ByteData data = await rootBundle.load(widget.recipe.baseImagePath);
|
|
final ui.Codec codec = await ui.instantiateImageCodec(
|
|
data.buffer.asUint8List(),
|
|
);
|
|
final ui.FrameInfo fi = await codec.getNextFrame();
|
|
|
|
if (mounted) {
|
|
setState(() {
|
|
_loadedImage = fi.image;
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
} catch (e) {
|
|
if (mounted) {
|
|
setState(() => _isLoading = false);
|
|
}
|
|
debugPrint("Error loading image: $e");
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final screenSize = MediaQuery.of(context).size;
|
|
final isSmallScreen = screenSize.width < 600 || screenSize.height < 800;
|
|
|
|
return Dialog(
|
|
backgroundColor: Colors.transparent,
|
|
insetPadding: EdgeInsets.all(isSmallScreen ? 8 : 16),
|
|
child: Container(
|
|
width: double.infinity,
|
|
height: double.infinity,
|
|
decoration: BoxDecoration(
|
|
color: Colors.black,
|
|
borderRadius: BorderRadius.circular(isSmallScreen ? 12 : 20),
|
|
),
|
|
child: Stack(
|
|
children: [
|
|
// 全屏壁纸预览
|
|
Positioned.fill(
|
|
child: ClipRRect(
|
|
borderRadius: BorderRadius.circular(isSmallScreen ? 12 : 20),
|
|
child: _buildWallpaperPreview(isSmallScreen),
|
|
),
|
|
),
|
|
// 顶部控制栏
|
|
Positioned(
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: isSmallScreen ? 12 : 20,
|
|
vertical: isSmallScreen ? 8 : 16,
|
|
),
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
Colors.black.withValues(alpha: 0.8),
|
|
Colors.transparent,
|
|
],
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
),
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
// 关闭按钮
|
|
IconButton(
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
icon: Icon(
|
|
Icons.close,
|
|
color: Colors.white,
|
|
size: isSmallScreen ? 20 : 24,
|
|
),
|
|
padding: EdgeInsets.all(isSmallScreen ? 4 : 8),
|
|
constraints: const BoxConstraints(),
|
|
),
|
|
// 预览模式切换
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.black.withValues(alpha: 0.5),
|
|
borderRadius: BorderRadius.circular(
|
|
isSmallScreen ? 16 : 20,
|
|
),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
_buildModeButton(
|
|
'Home',
|
|
Icons.home,
|
|
true,
|
|
isSmallScreen,
|
|
),
|
|
_buildModeButton(
|
|
'Lock',
|
|
Icons.lock,
|
|
false,
|
|
isSmallScreen,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildModeButton(
|
|
String label,
|
|
IconData icon,
|
|
bool isHome,
|
|
bool isSmallScreen,
|
|
) {
|
|
final isSelected = _isHomeScreen == isHome;
|
|
return GestureDetector(
|
|
onTap: () {
|
|
setState(() {
|
|
_isHomeScreen = isHome;
|
|
});
|
|
},
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: isSmallScreen ? 10 : 16,
|
|
vertical: isSmallScreen ? 6 : 8,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: isSelected ? Colors.pinkAccent : Colors.transparent,
|
|
borderRadius: BorderRadius.circular(isSmallScreen ? 12 : 16),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
icon,
|
|
color: isSelected ? Colors.white : Colors.grey[400],
|
|
size: isSmallScreen ? 14 : 16,
|
|
),
|
|
SizedBox(width: isSmallScreen ? 3 : 4),
|
|
Text(
|
|
label,
|
|
style: TextStyle(
|
|
color: isSelected ? Colors.white : Colors.grey[400],
|
|
fontSize: isSmallScreen ? 11 : 12,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildWallpaperPreview(bool isSmallScreen) {
|
|
if (_isLoading) {
|
|
return Container(
|
|
color: Colors.black,
|
|
child: const Center(
|
|
child: CircularProgressIndicator(color: Colors.pinkAccent),
|
|
),
|
|
);
|
|
}
|
|
|
|
if (_loadedImage == null) {
|
|
return Container(
|
|
color: Colors.grey[800],
|
|
child: const Center(
|
|
child: Icon(Icons.image_not_supported, color: Colors.grey, size: 60),
|
|
),
|
|
);
|
|
}
|
|
|
|
return Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
// 壁纸图片
|
|
CustomPaint(
|
|
painter: WallpaperPreviewPainter(
|
|
image: _loadedImage!,
|
|
recipe: widget.recipe,
|
|
),
|
|
child: Container(),
|
|
),
|
|
// UI覆盖层
|
|
_isHomeScreen
|
|
? _buildHomeScreenUI(isSmallScreen)
|
|
: _buildLockScreenUI(isSmallScreen),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildHomeScreenUI(bool isSmallScreen) {
|
|
return Stack(
|
|
children: [
|
|
// 模拟主页内容
|
|
Positioned(
|
|
top: isSmallScreen ? 30 : 50,
|
|
left: isSmallScreen ? 12 : 20,
|
|
right: isSmallScreen ? 12 : 20,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Good Morning',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: isSmallScreen ? 18 : 24,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
SizedBox(height: isSmallScreen ? 4 : 8),
|
|
Text(
|
|
'Monday, October 23',
|
|
style: TextStyle(
|
|
color: Colors.white.withValues(alpha: 0.8),
|
|
fontSize: isSmallScreen ? 13 : 16,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// 底部Dock
|
|
Positioned(
|
|
bottom: isSmallScreen ? 12 : 20,
|
|
left: isSmallScreen ? 12 : 20,
|
|
right: isSmallScreen ? 12 : 20,
|
|
child: Container(
|
|
padding: EdgeInsets.symmetric(
|
|
horizontal: isSmallScreen ? 12 : 20,
|
|
vertical: isSmallScreen ? 8 : 12,
|
|
),
|
|
decoration: BoxDecoration(
|
|
color: Colors.black.withValues(alpha: 0.3),
|
|
borderRadius: BorderRadius.circular(isSmallScreen ? 16 : 20),
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
_buildDockIcon(Icons.phone, isSmallScreen),
|
|
_buildDockIcon(Icons.message, isSmallScreen),
|
|
_buildDockIcon(Icons.camera_alt, isSmallScreen),
|
|
_buildDockIcon(Icons.music_note, isSmallScreen),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildLockScreenUI(bool isSmallScreen) {
|
|
return Stack(
|
|
children: [
|
|
// 时间显示
|
|
Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Text(
|
|
'9:41',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: isSmallScreen ? 36 : 48,
|
|
fontWeight: FontWeight.w300,
|
|
),
|
|
),
|
|
SizedBox(height: isSmallScreen ? 4 : 8),
|
|
Text(
|
|
'Monday, October 23',
|
|
style: TextStyle(
|
|
color: Colors.white.withValues(alpha: 0.8),
|
|
fontSize: isSmallScreen ? 13 : 16,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// 底部控制
|
|
Positioned(
|
|
bottom: isSmallScreen ? 30 : 50,
|
|
left: 0,
|
|
right: 0,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
_buildLockIcon(Icons.flashlight_off, isSmallScreen),
|
|
_buildLockIcon(Icons.camera_alt, isSmallScreen),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildDockIcon(IconData icon, bool isSmallScreen) {
|
|
return Container(
|
|
padding: EdgeInsets.all(isSmallScreen ? 8 : 12),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white.withValues(alpha: 0.1),
|
|
borderRadius: BorderRadius.circular(isSmallScreen ? 10 : 12),
|
|
),
|
|
child: Icon(icon, color: Colors.white, size: isSmallScreen ? 20 : 24),
|
|
);
|
|
}
|
|
|
|
Widget _buildLockIcon(IconData icon, bool isSmallScreen) {
|
|
return Container(
|
|
padding: EdgeInsets.all(isSmallScreen ? 12 : 16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white.withValues(alpha: 0.2),
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Icon(icon, color: Colors.white, size: isSmallScreen ? 20 : 24),
|
|
);
|
|
}
|
|
}
|