generated from dellevin/template
优化名称编辑弹窗
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import '../../data/gallery/gallery_dao.dart';
|
||||
@@ -180,17 +182,11 @@ class _GalleryPageState extends State<GalleryPage> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 图片
|
||||
AspectRatio(
|
||||
aspectRatio: _aspectRatioFor(item.category),
|
||||
child: FadeInLocalImage(
|
||||
path: item.path,
|
||||
fit: BoxFit.cover,
|
||||
errorWidget: Container(
|
||||
color: colors.surfaceContainerHighest,
|
||||
child: Icon(Icons.broken_image_outlined, color: colors.onSurface.withValues(alpha: 0.3)),
|
||||
),
|
||||
),
|
||||
// 图片(按真实比例显示)
|
||||
_GalleryImageCard(
|
||||
path: item.path,
|
||||
fallbackAspectRatio: _aspectRatioFor(item.category),
|
||||
colors: colors,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// 类别标签
|
||||
@@ -228,7 +224,7 @@ class _GalleryPageState extends State<GalleryPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// 不同类别用不同宽高比,让瀑布流有错落感
|
||||
/// 不同类别用作加载占位的默认宽高比;图片真实尺寸读出后会被覆盖
|
||||
double _aspectRatioFor(String category) {
|
||||
switch (category) {
|
||||
case 'movie_poster':
|
||||
@@ -265,3 +261,79 @@ class _GalleryPageState extends State<GalleryPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 读取本地图片真实宽高,按真实比例显示;未读出前用 fallback 占位。
|
||||
class _GalleryImageCard extends StatefulWidget {
|
||||
final String path;
|
||||
final double fallbackAspectRatio;
|
||||
final ColorScheme colors;
|
||||
|
||||
const _GalleryImageCard({
|
||||
required this.path,
|
||||
required this.fallbackAspectRatio,
|
||||
required this.colors,
|
||||
});
|
||||
|
||||
@override
|
||||
State<_GalleryImageCard> createState() => _GalleryImageCardState();
|
||||
}
|
||||
|
||||
class _GalleryImageCardState extends State<_GalleryImageCard> {
|
||||
double? _aspectRatio;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_resolveAspectRatio();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(_GalleryImageCard oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.path != widget.path) {
|
||||
_aspectRatio = null;
|
||||
_resolveAspectRatio();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _resolveAspectRatio() async {
|
||||
final path = widget.path;
|
||||
try {
|
||||
if (path.startsWith('http')) {
|
||||
// 网络图片不解析尺寸,直接用占位比例
|
||||
return;
|
||||
}
|
||||
final file = File(path);
|
||||
if (!await file.exists()) return;
|
||||
final bytes = await file.readAsBytes();
|
||||
if (!mounted) return;
|
||||
final data = Uint8List.fromList(bytes);
|
||||
final decoded = await decodeImageFromList(data);
|
||||
if (!mounted) return;
|
||||
if (decoded.width > 0 && decoded.height > 0) {
|
||||
setState(() => _aspectRatio = decoded.width / decoded.height);
|
||||
}
|
||||
} catch (_) {
|
||||
// 解析失败则保留占位比例
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ratio = _aspectRatio ?? widget.fallbackAspectRatio;
|
||||
return AspectRatio(
|
||||
aspectRatio: ratio,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: FadeInLocalImage(
|
||||
path: widget.path,
|
||||
fit: BoxFit.cover,
|
||||
errorWidget: Container(
|
||||
color: widget.colors.surfaceContainerHighest,
|
||||
child: Icon(Icons.broken_image_outlined, color: widget.colors.onSurface.withValues(alpha: 0.3)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user