QinGang_interested/lib/customWidget/single_images_viewer.dart

148 lines
4.3 KiB
Dart
Raw Permalink Normal View History

2026-04-15 17:41:33 +08:00
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:qhd_prevention/pages/my_appbar.dart';
class SingleImagesViewer extends StatefulWidget {
final String imageUrl;
/// 可选多张图片列表。如果需要列表的话imageUrl可以传空
final List<String>? imageUrls;
/// 可选:初始显示页(默认 0
final int initialIndex;
const SingleImagesViewer({
Key? key,
required this.imageUrl,
this.imageUrls,
this.initialIndex = 0,
}) : super(key: key);
@override
State<SingleImagesViewer> createState() => _SingleImagesViewerState();
}
class _SingleImagesViewerState extends State<SingleImagesViewer> {
late final List<String> _urls;
late final PageController _pageController;
int _currentIndex = 0;
@override
void initState() {
super.initState();
// 优先使用 imageUrls
if (widget.imageUrls != null && widget.imageUrls!.isNotEmpty) {
_urls = widget.imageUrls!;
} else {
_urls = [widget.imageUrl];
}
_currentIndex = (widget.initialIndex >= 0 && widget.initialIndex < _urls.length)
? widget.initialIndex
: 0;
_pageController = PageController(initialPage: _currentIndex);
}
ImageProvider _providerFromUrl(String imageUrl) {
final lower = imageUrl.toLowerCase();
if (lower.startsWith('http')) {
return NetworkImage(imageUrl);
} else if (imageUrl.startsWith('assets/') ||
imageUrl.startsWith('package:') ||
imageUrl.startsWith('packages/')) {
return AssetImage(imageUrl);
} else {
if (!kIsWeb) {
try {
final file = File(imageUrl);
if (file.existsSync()) {
return FileImage(file);
} else {
return AssetImage(imageUrl);
}
} catch (e) {
return AssetImage(imageUrl);
}
} else {
return AssetImage(imageUrl);
}
}
}
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
Color _bgColor() => Colors.black.withOpacity(0.9);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: _bgColor(),
appBar: MyAppbar(
isBack: false,
actions: [
IconButton(
onPressed: () => Navigator.of(context).pop(),
icon: const Icon(
Icons.close,
color: Colors.white,
size: 40,
),
),
],
backgroundColor: _bgColor(),
title: '',
),
body: Stack(
children: [
PhotoViewGallery.builder(
pageController: _pageController,
itemCount: _urls.length,
onPageChanged: (index) => setState(() => _currentIndex = index),
builder: (context, index) {
final url = _urls[index];
return PhotoViewGalleryPageOptions(
imageProvider: _providerFromUrl(url),
minScale: PhotoViewComputedScale.contained,
maxScale: PhotoViewComputedScale.covered * 2,
onTapUp: (context, details, controllerValue) {
Navigator.of(context).pop();
},
);
},
backgroundDecoration: BoxDecoration(color: _bgColor()),
// enableRotation: false, // 如果需要可打开旋转
loadingBuilder: (context, progress) => const Center(
child: CircularProgressIndicator(),
),
),
// 页码指示
if (_urls.length > 1)
Positioned(
right: 12,
top: 12 + MediaQuery.of(context).padding.top,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.45),
borderRadius: BorderRadius.circular(16),
),
child: Text(
'${_currentIndex + 1} / ${_urls.length}',
style: const TextStyle(color: Colors.white, fontSize: 14),
),
),
),
],
),
);
}
}