import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:aesthetica_wallpaper/models/image_category.dart'; import 'package:aesthetica_wallpaper/providers/editor_provider.dart'; import 'package:aesthetica_wallpaper/screens/puzzle/drag_puzzle_menu_screen.dart'; import 'package:aesthetica_wallpaper/screens/home/recommendation_list_screen.dart'; import 'dart:math' as math; import '../aigenerate/ai_generate.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State createState() => _HomeScreenState(); } class _HomeScreenState extends State with SingleTickerProviderStateMixin { late Future> _categoriesFuture; late PageController _bannerController; late AnimationController _animationController; @override void initState() { super.initState(); _categoriesFuture = _loadCategories(); _bannerController = PageController(); _animationController = AnimationController( vsync: this, duration: const Duration(seconds: 2), )..repeat(); // 自动轮播Banner Future.delayed(const Duration(seconds: 3), _autoPlayBanner); } void _autoPlayBanner() { if (!mounted) return; _bannerController.nextPage( duration: const Duration(milliseconds: 500), curve: Curves.easeInOut, ); Future.delayed(const Duration(seconds: 3), _autoPlayBanner); } @override void dispose() { _bannerController.dispose(); _animationController.dispose(); super.dispose(); } // 直接读取assets文件夹中的图片 Future> _loadCategories() async { final categories = []; // 定义类别配置 final categoryConfigs = [ {'name': 'Nature', 'folder': 'nature'}, {'name': 'Abstract', 'folder': 'abstract'}, {'name': 'Architecture', 'folder': 'architecture'}, {'name': 'Animals', 'folder': 'animals'}, {'name': 'Food', 'folder': 'food'}, {'name': 'Travel', 'folder': 'travel'}, ]; for (final config in categoryConfigs) { try { // 尝试读取文件夹中的图片 final images = await _getImagesFromFolder(config['folder']!); if (images.isNotEmpty) { categories.add( ImageCategory( name: config['name']!, folder: config['folder']!, images: images, ), ); } } catch (e) { debugPrint('Error loading category ${config['name']}: $e'); } } return categories; } // 获取指定文件夹中的所有图片 Future> _getImagesFromFolder(String folderName) async { // 根据实际assets文件夹中的图片文件列表 final knownImages = { 'nature': [ 'nature1.png', 'nature2.png', 'nature3.png', 'nature4.png', 'nature5.png', 'nature6.png', 'nature7.png', 'nature8.png', 'nature9.png', ], 'abstract': [ 'abstract1.png', 'abstract2.png', 'abstract3.png', 'abstract4.png', 'abstract5.png', 'abstract6.png', 'abstract7.png', 'abstract8.png', 'abstract9.png', 'abstract10.png', 'abstract11.png', 'abstract12.png', 'abstract13.png', 'abstract14.png', 'abstract15.png', ], 'architecture': [ 'architecture1.png', 'architecture2.png', 'architecture3.png', 'architecture4.png', 'architecture5.png', 'architecture6.png', 'architecture7.png', 'architecture8.png', 'architecture9.png', 'architecture10.png', ], 'animals': [ 'animals1.png', 'animals2.png', 'animals3.png', 'animals4.png', 'animals5.png', 'animals6.png', 'animals7.png', ], 'food': [ 'food1.png', 'food2.png', 'food3.png', 'food4.png', 'food5.png', 'food6.png', 'food7.png', 'food8.png', 'food9.png', 'food10.png', 'food11.png', 'food12.png', 'food13.png', ], 'travel': [ 'travel5.png', 'travel1.png', 'travel2.png', 'travel3.png', 'travel4.png', 'travel6.png', 'travel7.png', 'travel8.png', 'travel9.png', ], }; return knownImages[folderName] ?? []; } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder>( future: _categoriesFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } if (snapshot.hasError) { return Center( child: Text('Error loading categories: ${snapshot.error}'), ); } if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text('No categories found.')); } final categories = snapshot.data!; return CustomScrollView( slivers: [ // 美化的AppBar _buildSliverAppBar(), // Banner轮播 SliverToBoxAdapter(child: _buildBannerSection(categories)), // 快速功能入口 SliverToBoxAdapter(child: _buildQuickActions()), // 每日推荐 SliverToBoxAdapter(child: _buildDailyRecommendation(categories)), // 热门分类标题 SliverToBoxAdapter( child: _buildSectionTitle( 'Categories', 'Explore beautiful wallpapers', ), ), // 分类网格 SliverPadding( padding: const EdgeInsets.symmetric(horizontal: 16), sliver: SliverGrid( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 12, crossAxisSpacing: 12, childAspectRatio: 0.75, ), delegate: SliverChildBuilderDelegate((context, index) { return _buildCategoryGridItem(context, categories[index]); }, childCount: categories.length), ), ), // 底部间距 const SliverToBoxAdapter(child: SizedBox(height: 100)), ], ); }, ), ); } // 美化的SliverAppBar Widget _buildSliverAppBar() { return SliverAppBar( expandedHeight: 120, floating: false, pinned: true, flexibleSpace: FlexibleSpaceBar( title: const Text( 'MoodCanvas', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24), ), background: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Colors.purple.shade400, Colors.blue.shade400], ), ), ), ), ); } // Banner轮播区域 - 只保留两个:拼图和推荐 Widget _buildBannerSection(List categories) { final bannerItems = [ { 'title': '🎮 Puzzle Game', 'subtitle': 'Challenge your mind with wall papers', 'color': Colors.purple, 'icon': Icons.extension, 'action': 'puzzle', }, { 'title': '⭐ Daily Picks', 'subtitle': 'Discover today\'s best wallpapers', 'color': Colors.orange, 'icon': Icons.star, 'action': 'recommendation', }, ]; return Container( height: 145, margin: const EdgeInsets.symmetric(vertical: 16), child: PageView.builder( controller: _bannerController, itemCount: bannerItems.length, itemBuilder: (context, index) { final item = bannerItems[index]; return _buildBannerItem( item['title'] as String, item['subtitle'] as String, item['color'] as Color, item['icon'] as IconData, item['action'] as String, ); }, ), ); } Widget _buildBannerItem( String title, String subtitle, Color color, IconData icon, String action, ) { return Container( margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [color, color.withValues(alpha: 0.7)], ), boxShadow: [ BoxShadow( color: color.withValues(alpha: 0.3), blurRadius: 15, offset: const Offset(0, 8), ), ], ), child: Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(20), onTap: () { if (action == 'puzzle') { Navigator.push( context, MaterialPageRoute( builder: (context) => const DragPuzzleMenuScreen(), ), ); } else if (action == 'recommendation') { Navigator.push( context, MaterialPageRoute( builder: (context) => const RecommendationListScreen(), ), ); } }, child: Padding( padding: const EdgeInsets.all(24), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( title, style: const TextStyle( color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( subtitle, style: TextStyle( color: Colors.white.withValues(alpha: 0.9), fontSize: 14, ), ), ], ), ), AnimatedBuilder( animation: _animationController, builder: (context, child) { return Transform.rotate( angle: _animationController.value * 2 * math.pi, child: Icon( icon, size: 60, color: Colors.white.withValues(alpha: 0.3), ), ); }, ), ], ), ), ), ), ); } // 快速功能入口 - 只保留拼图和AI生成 Widget _buildQuickActions() { final actions = [ {'icon': Icons.extension, 'label': 'Puzzle', 'color': Colors.purple}, { 'icon': Icons.auto_awesome, 'label': 'AI Generate', 'color': Colors.blue, }, ]; return Container( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Row( children: [ Expanded( child: _buildQuickActionItem( actions[0]['icon'] as IconData, actions[0]['label'] as String, actions[0]['color'] as Color, ), ), const SizedBox(width: 12), Expanded( child: _buildQuickActionItem( actions[1]['icon'] as IconData, actions[1]['label'] as String, actions[1]['color'] as Color, ), ), ], ), ); } Widget _buildQuickActionItem(IconData icon, String label, Color color) { return InkWell( onTap: () { // 根据不同功能跳转 if (label == 'Puzzle') { Navigator.push( context, MaterialPageRoute( builder: (context) => const DragPuzzleMenuScreen(), ), ); } else { //AI Generate Navigator.push( context, MaterialPageRoute(builder: (context) => const ParticleHomePage()), ); } }, borderRadius: BorderRadius.circular(16), child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ color.withValues(alpha: 0.2), color.withValues(alpha: 0.1), ], ), borderRadius: BorderRadius.circular(16), border: Border.all(color: color.withValues(alpha: 0.3), width: 1), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: color.withValues(alpha: 0.15), shape: BoxShape.circle, ), child: Icon(icon, color: color, size: 36), ), const SizedBox(height: 12), Text( label, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: color, ), textAlign: TextAlign.center, ), ], ), ), ); } // 每日推荐区域 Widget _buildDailyRecommendation(List categories) { if (categories.isEmpty) return const SizedBox.shrink(); final random = math.Random(); final randomCategory = categories[random.nextInt(categories.length)]; final randomImages = randomCategory.images.take(5).toList(); return Column( children: [ _buildSectionTitle('Daily Picks', 'Curated wallpapers for you'), SizedBox( height: 150, child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: randomImages.length, itemBuilder: (context, index) { return _buildRecommendationItem( randomCategory.folder, randomImages[index], ); }, ), ), ], ); } Widget _buildRecommendationItem(String folder, String imageName) { final imagePath = 'assets/images/$folder/$imageName'; return GestureDetector( onTap: () { // 初始化编辑器并跳转 Provider.of( context, listen: false, ).startEditing(imagePath); Navigator.pushNamed(context, '/editor'); }, child: Container( width: 140, margin: const EdgeInsets.only(right: 12), child: ClipRRect( borderRadius: BorderRadius.circular(16), child: Stack( fit: StackFit.expand, children: [ Image.asset(imagePath, fit: BoxFit.cover), Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withValues(alpha: 0.5), ], ), ), ), const Positioned( bottom: 8, left: 8, right: 8, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Icon(Icons.favorite_border, color: Colors.white, size: 20), Icon(Icons.edit, color: Colors.white, size: 20), ], ), ), ], ), ), ), ); } // 区域标题 Widget _buildSectionTitle(String title, String subtitle) { return Padding( padding: const EdgeInsets.fromLTRB(16, 24, 16, 16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( subtitle, style: TextStyle(fontSize: 14, color: Colors.grey.shade600), ), ], ), ], ), ); } // 分类网格项 Widget _buildCategoryGridItem(BuildContext context, ImageCategory category) { return InkWell( onTap: () { Navigator.pushNamed(context, '/gallery', arguments: category); }, borderRadius: BorderRadius.circular(16), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.1), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(16), child: Stack( fit: StackFit.expand, children: [ Image.asset(category.getThumbnailPath(), fit: BoxFit.cover), Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Colors.transparent, Colors.black.withValues(alpha: 0.7), ], ), ), ), Positioned( bottom: 12, left: 12, right: 12, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( category.name, style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Text( '${category.images.length} wallpapers', style: TextStyle( color: Colors.white.withValues(alpha: 0.8), fontSize: 12, ), ), ], ), ), ], ), ), ), ); } }