STM32H743双核实战指南:480MHz性能落地的关键陷阱与决策逻辑
2026/9/9 9:55:59
效果图
代码实例
local_album_page UI主页面
import 'dart:math'; import 'package:flutter/material.dart'; import 'package:my_flutter/photo_detail_page.dart'; import '../local_photos.dart'; ///本地相册页面 class LocalAlbumPage extends StatefulWidget { const LocalAlbumPage({super.key}); @override State<StatefulWidget> createState() => _LocalAlbumPageState(); } class _LocalAlbumPageState extends State<LocalAlbumPage> { late List<LocalPhotos> photoList;// 照片数据列表 bool isDeleteState = false; //全局是否处于删除状态 // 文本资源 String localAlbum = "本地相册"; @override void initState() { super.initState(); // 生成模拟照片数据 photoList = generateMockPhotos(); } // 生成模拟照片数据 List<LocalPhotos> generateMockPhotos() { final List<LocalPhotos> photos = []; final Random random = Random(); // 模拟照片路径(使用网络图片或本地占位图) final List<String> mockImageUrls = [ 'https://picsum.photos/seed/1/400/400', 'https://picsum.photos/seed/2/400/400', 'https://picsum.photos/seed/3/400/400', 'https://picsum.photos/seed/4/400/400', 'https://picsum.photos/seed/5/400/400', 'https://picsum.photos/seed/6/400/400', 'https://picsum.photos/seed/7/400/400', 'https://picsum.photos/seed/8/400/400', 'https://picsum.photos/seed/9/400/400', 'https://picsum.photos/seed/10/400/400', 'https://picsum.photos/seed/11/400/400', 'https://picsum.photos/seed/12/400/400', 'https://picsum.photos/seed/13/400/400', 'https://picsum.photos/seed/14/400/400', 'https://picsum.photos/seed/15/400/400', ]; // 生成过去30天的随机日期 final DateTime now = DateTime.now(); for (int i = 0; i < 30; i++) { // 随机选择过去30天内的某一天 final int daysAgo = random.nextInt(30); final DateTime photoDate = now.subtract(Duration(days: daysAgo)); // 格式化日期为 "2024-01-15" final String dateStr = '${photoDate.year}-${photoDate.month.toString().padLeft(2, '0')}-${photoDate.day.toString().padLeft(2, '0')}'; // 随机选择图片(可以重复) final String imageUrl = mockImageUrls[random.nextInt(mockImageUrls.length)]; photos.add(LocalPhotos( date: dateStr, photoPath: imageUrl, isSelected:false, )); } // 按日期排序(最新在前面) photos.sort((a, b) => b.date.compareTo(a.date)); return photos; } // 删除选中的照片 void deleteSelectedPhotos() { setState(() { photoList.removeWhere((photo) => photo.isSelected); isDeleteState = false; }); } //////////////////////////////////////////////////////////////////////////////////////// @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xFFF5FCFF), appBar: AppBar( backgroundColor: Color(0xFFF5FCFF), leading: IconButton( onPressed: () { Navigator.pop(context); }, icon: Icon(Icons.arrow_back_ios,color: Colors.black,), ), title: Text( localAlbum, style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold), ), centerTitle: true, actions: [ isDeleteState? Text("全选") :IconButton( onPressed: () { //进入全选状态 setState(() { isDeleteState = true; }); }, icon: Icon(Icons.select_all), ), ], ), body: Stack( children: [ Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 20), // 照片网格 Expanded( child: _buildPhotoGrid(), ), ], ), //删除悬浮按钮 isDeleteState? Positioned( bottom: 30, left: 0, right: 0, child: Center( child:Container( height: 52, width: 127, padding: EdgeInsets.symmetric(vertical: 5), decoration: BoxDecoration( color: Colors.black.withOpacity(0.3), borderRadius: BorderRadius.circular(26), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.center, children: [ //分享 GestureDetector( onTap: (){ }, child: Column( children: [ Icon(Icons.share,color: Colors.white,), SizedBox(height: 4,), Text("分享",style: TextStyle(color: Colors.white,fontSize: 8),), ], ), ), //删除 GestureDetector( onTap: (){ deleteSelectedPhotos(); }, child: Column( children: [ Icon(Icons.delete,color: Colors.white,), SizedBox(height: 4,), Text("删除",style: TextStyle(color: Colors.white,fontSize: 8),), ], ), ), ], ), ), ) ):SizedBox.shrink() ], ) ); } //=============================构建照片网格================================= Widget _buildPhotoGrid() { // 按日期分组 final Map<String, List<LocalPhotos>> groupedPhotos = {}; for (var photo in photoList) { if (!groupedPhotos.containsKey(photo.date)) { groupedPhotos[photo.date] = []; } groupedPhotos[photo.date]!.add(photo); } // 获取排序后的日期列表(最新在前面) final List<String> sortedDates = groupedPhotos.keys.toList()..sort((a, b) => b.compareTo(a)); return ListView.builder( padding: EdgeInsets.symmetric(horizontal: 16), itemCount: sortedDates.length, itemBuilder: (context, index) { final String date = sortedDates[index]; final List<LocalPhotos> photosOfDay = groupedPhotos[date]!; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 日期标题 Padding( padding: EdgeInsets.symmetric(vertical: 12), child: Text( _formatDateDisplay(date), style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, color: Colors.black, ), ), ), // 该日期的照片网格 GridView.builder( shrinkWrap: true, // 让 GridView 在 ListView 中自适应 physics: NeverScrollableScrollPhysics(), // 禁止内部滚动 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, // 每行3列 crossAxisSpacing: 4, mainAxisSpacing: 4, childAspectRatio: 1, // 正方形 ), itemCount: photosOfDay.length, itemBuilder: (context, photoIndex) { return _buildPhotoItem(photosOfDay[photoIndex]); }, ), SizedBox(height: 8), ], ); }, ); } //============================构建单张照片============================== Widget _buildPhotoItem(LocalPhotos photo) { return GestureDetector( onTap: (){ //单击进入详细页面 if (!isDeleteState) { Navigator.push( context, MaterialPageRoute( builder: (context) => PhotoDetailPage(photo: photo), ), ); } }, child: ClipRRect( borderRadius: BorderRadius.circular(26), child: Stack( fit: StackFit.expand, children: [ // 底层:图片 Image.network( photo.photoPath, fit: BoxFit.cover, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) { return child; } return Container( color: Colors.grey[200], child: Center( child: CircularProgressIndicator( value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! : null, strokeWidth: 2, ), ), ); }, errorBuilder: (context, error, stackTrace) { return Container( color: Colors.grey[300], child: Icon(Icons.broken_image, color: Colors.grey[600]), ); }, ), //圆环图标(始终显示) isDeleteState?Positioned( right: 8, top: 8, child:GestureDetector( onTap: (){ setState(() { photo.isSelected = !photo.isSelected; }); }, child: Container( height: 20, width: 20, child: photo.isSelected? Icon(Icons.check_circle,color: Colors.white,):Icon(Icons.circle_outlined,color: Colors.white) ), ) ):SizedBox.shrink() ], ), ), ); } // 格式化日期显示 String _formatDateDisplay(String dateStr) { final parts = dateStr.split('-'); if (parts.length != 3) return dateStr; final year = parts[0]; final month = parts[1]; final day = parts[2]; // 判断是否是今天、昨天等 final DateTime now = DateTime.now(); final DateTime today = DateTime(now.year, now.month, now.day); final DateTime photoDate = DateTime( int.parse(year), int.parse(month), int.parse(day) ); final int difference = today.difference(photoDate).inDays; if (difference == 0) { return '今天'; } else if (difference == 1) { return '昨天'; } else if (difference <= 7) { return '${difference}天前'; } else { // 返回 "2024年1月15日" 格式 return '${year}年${int.parse(month)}月${int.parse(day)}日'; } } }photo_detail_page 照片详情页面
import 'package:flutter/material.dart'; import 'local_photos.dart'; /// 照片展示页面 - 显示照片原始尺寸 class PhotoDetailPage extends StatefulWidget { const PhotoDetailPage({ super.key, required this.photo, }); final LocalPhotos photo; @override State<StatefulWidget> createState() => _PhotoDetailPageState(); } class _PhotoDetailPageState extends State<PhotoDetailPage> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, elevation: 0, leading: IconButton( onPressed: () { Navigator.pop(context); }, icon: Icon(Icons.arrow_back_ios, color: Colors.black), ), actions: [ Text( _formatDate(widget.photo.date), style: TextStyle(color: Colors.black, fontSize: 20), ), ], ), body: Stack( children: [ //背景图 Center( child: Image.network( widget.photo.photoPath, fit: BoxFit.fitWidth, loadingBuilder: (context, child, loadingProgress) { if (loadingProgress == null) return child; return Container( width: 300, height: 300, color: Colors.grey[900], child: Center( child: CircularProgressIndicator( value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! : null, color: Colors.white, ), ), ); }, errorBuilder: (context, error, stackTrace) { return Container( width: 300, height: 300, color: Colors.grey[900], child: Center( child: Icon(Icons.broken_image, color: Colors.grey[600], size: 64), ), ); }, ), ), //底部按钮 Positioned( bottom: 20, right: 0, left: 0, child: Center( child: Container( height: 52, width: 270, padding: EdgeInsets.symmetric(vertical: 5), decoration: BoxDecoration( color: Color(0xFF000000).withOpacity(0.3), borderRadius: BorderRadius.circular(26), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ //智能分析 GestureDetector( child: Column( children: [ Icon(Icons.analytics,color: Colors.white,), SizedBox(height: 4,), Text("智能分析",style: TextStyle(color: Colors.white,fontSize: 8),) ], ) ), //下载 GestureDetector( child: Column( children: [ Icon(Icons.download,color: Colors.white,), SizedBox(height: 4,), Text("下载",style: TextStyle(color: Colors.white,fontSize: 8),) ], ) ), //分析 GestureDetector( child: Column( children: [ Icon(Icons.share,color: Colors.white,), SizedBox(height: 4,), Text("分享",style: TextStyle(color: Colors.white,fontSize: 8),) ], ) ), //删除 GestureDetector( child: Column( children: [ Icon(Icons.delete,color: Colors.white,), SizedBox(height: 4,), Text("删除",style: TextStyle(color: Colors.white,fontSize: 8),) ], ) ), ], ), ), ), ) ], ) ); } // 👇 格式化日期为 "2024年1月15日" 格式 String _formatDate(String dateStr) { final parts = dateStr.split('-'); if (parts.length != 3) return dateStr; final year = parts[0]; final month = int.parse(parts[1]); // 转成数字去掉前导0 final day = int.parse(parts[2]); return '${year}年${month}月${day}日'; } }照片类
///本地照片类 class LocalPhotos { String date;//日期 String photoPath; //照片路径 bool isSelected; //是否被选中 LocalPhotos({ required this.date, required this.photoPath, this.isSelected = false, //默认未选中 }); //复制方法 LocalPhotos copyWith({ String? date, String? photoPath, bool? isSelected, }){ return LocalPhotos( date: date ?? this.date, photoPath: photoPath ?? this.photoPath, isSelected: isSelected ?? this.isSelected, ); } }