feat:更新菜谱显示模块
This commit is contained in:
@@ -19,6 +19,7 @@ class ImagePreviewPage extends StatefulWidget {
|
||||
class _ImagePreviewPageState extends State<ImagePreviewPage> {
|
||||
// 声明 PageController 并初始化初始索引
|
||||
late PageController _pageController;
|
||||
|
||||
// 记录当前显示的图片索引(用于更新页码)
|
||||
int _currentIndex = 0;
|
||||
|
||||
@@ -68,17 +69,18 @@ class _ImagePreviewPageState extends State<ImagePreviewPage> {
|
||||
centerTitle: true,
|
||||
),
|
||||
body: PhotoViewGallery(
|
||||
pageOptions: widget.images.map((url) {
|
||||
return PhotoViewGalleryPageOptions(
|
||||
imageProvider: NetworkImage(url),
|
||||
minScale: PhotoViewComputedScale.contained,
|
||||
maxScale: PhotoViewComputedScale.covered * 2,
|
||||
// 点击空白处关闭预览
|
||||
onTapDown: (context, details, controllerValue) {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
pageOptions:
|
||||
widget.images.map((url) {
|
||||
return PhotoViewGalleryPageOptions(
|
||||
imageProvider: NetworkImage(url),
|
||||
minScale: PhotoViewComputedScale.contained,
|
||||
maxScale: PhotoViewComputedScale.covered * 2,
|
||||
// 点击空白处关闭预览
|
||||
onTapDown: (context, details, controllerValue) {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
pageController: _pageController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
),
|
||||
@@ -86,30 +88,94 @@ class _ImagePreviewPageState extends State<ImagePreviewPage> {
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildNetworkImage(String url) {
|
||||
Widget buildNetworkImage(BuildContext context, String url) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Image.network(
|
||||
url,
|
||||
fit: BoxFit.cover,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
// 加载中显示占位符
|
||||
if (loadingProgress == null) return child;
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
value: loadingProgress.expectedTotalBytes != null
|
||||
? loadingProgress.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: null,
|
||||
),
|
||||
);
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
_showFullScreenImage(context, url);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Container(
|
||||
color: Colors.grey[200],
|
||||
child: const Icon(Icons.image, color: Colors.grey, size: 30),
|
||||
child: Image.network(
|
||||
url,
|
||||
fit: BoxFit.cover,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
return _buildLoadingIndicator(loadingProgress);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) => _buildErrorImage(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLoadingIndicator(ImageChunkEvent? loadingProgress) {
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: CircularProgressIndicator(
|
||||
value:
|
||||
loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildErrorImage() {
|
||||
return Container(
|
||||
color: Colors.grey[200],
|
||||
child: const Icon(Icons.image, color: Colors.grey, size: 30),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPhotoView(String url) {
|
||||
return PhotoView(
|
||||
imageProvider: NetworkImage(url),
|
||||
backgroundDecoration: const BoxDecoration(color: Colors.transparent),
|
||||
minScale: PhotoViewComputedScale.contained,
|
||||
maxScale: PhotoViewComputedScale.covered * 2,
|
||||
initialScale: PhotoViewComputedScale.contained,
|
||||
heroAttributes: PhotoViewHeroAttributes(tag: url),
|
||||
loadingBuilder: (context, event) => _buildLoadingIndicator(event),
|
||||
errorBuilder: (context, error, stackTrace) => _buildErrorImage(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCloseImage(BuildContext context) {
|
||||
return Positioned(
|
||||
top: MediaQuery.of(context).padding.top + 10,
|
||||
right: 20,
|
||||
child: IconButton(
|
||||
icon: Icon(Icons.close, color: Colors.white, size: 30),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showFullScreenImage(BuildContext context, String url) {
|
||||
Navigator.of(context).push(
|
||||
PageRouteBuilder(
|
||||
opaque: false,
|
||||
pageBuilder: (
|
||||
BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black.withAlpha(200),
|
||||
body: Stack(
|
||||
children: [
|
||||
// 可缩放图片
|
||||
Positioned.fill(child: _buildPhotoView(url)),
|
||||
// 关闭按钮
|
||||
_buildCloseImage(context),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user