196 lines
5.6 KiB
Dart
196 lines
5.6 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:video_player/video_player.dart';
|
|
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
|
|
|
|
class FullscreenImagePage extends StatefulWidget {
|
|
final AssetEntity? asset;
|
|
final String? networkUrl;
|
|
final Function(AssetEntity) onReplace;
|
|
|
|
const FullscreenImagePage({
|
|
super.key,
|
|
this.asset,
|
|
this.networkUrl,
|
|
required this.onReplace,
|
|
});
|
|
|
|
@override
|
|
State<FullscreenImagePage> createState() => _FullscreenImagePageState();
|
|
}
|
|
|
|
class _FullscreenImagePageState extends State<FullscreenImagePage> {
|
|
VideoPlayerController? _videoController;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
if (widget.asset?.type == AssetType.video) {
|
|
_initializeVideoPlayer();
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_videoController?.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
Future<void> _initializeVideoPlayer() async {
|
|
if (widget.asset == null) return;
|
|
final file = await widget.asset!.file;
|
|
if (file != null) {
|
|
_videoController = VideoPlayerController.file(file)
|
|
..initialize().then((_) {
|
|
setState(() {});
|
|
_videoController!.play();
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// 获取状态栏和AppBar的总高度
|
|
final double topPadding = MediaQuery.of(context).padding.top;
|
|
final double appBarHeight = AppBar().preferredSize.height;
|
|
final double totalTopHeight = topPadding + appBarHeight;
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
leading: IconButton(
|
|
icon: Image.asset('images/close.png', width: 16, height: 16),
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
),
|
|
),
|
|
body: Container(
|
|
width: double.infinity,
|
|
height: double.infinity,
|
|
decoration: const BoxDecoration(color: Color(0xff0C0C16)),
|
|
child: Stack(
|
|
children: [
|
|
Center(
|
|
child: Padding(
|
|
padding: EdgeInsets.only(bottom: totalTopHeight / 2),
|
|
child: widget.asset != null
|
|
? _buildAssetPreview()
|
|
: _buildNetworkImagePreview(),
|
|
),
|
|
),
|
|
Positioned(
|
|
right: 10,
|
|
bottom: 30,
|
|
child: _buildReplaceButton(),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildAssetPreview() {
|
|
return FutureBuilder<File?>(
|
|
future: widget.asset!.file,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.done &&
|
|
snapshot.hasData) {
|
|
if (widget.asset!.type == AssetType.video) {
|
|
return _videoController != null &&
|
|
_videoController!.value.isInitialized
|
|
? AspectRatio(
|
|
aspectRatio: _videoController!.value.aspectRatio,
|
|
child: VideoPlayer(_videoController!),
|
|
)
|
|
: const Center(child: CircularProgressIndicator());
|
|
}
|
|
return Container(
|
|
constraints: BoxConstraints(
|
|
maxWidth: MediaQuery.of(context).size.width,
|
|
maxHeight: MediaQuery.of(context).size.height * 0.7,
|
|
),
|
|
child: Image.file(
|
|
snapshot.data!,
|
|
fit: BoxFit.contain,
|
|
),
|
|
);
|
|
}
|
|
return const Center(child: CircularProgressIndicator());
|
|
},
|
|
);
|
|
}
|
|
|
|
Widget _buildNetworkImagePreview() {
|
|
if (widget.networkUrl == null) return const SizedBox();
|
|
|
|
return Container(
|
|
constraints: BoxConstraints(
|
|
maxWidth: MediaQuery.of(context).size.width,
|
|
maxHeight: MediaQuery.of(context).size.height * 0.7,
|
|
),
|
|
child: Image.network(
|
|
widget.networkUrl!,
|
|
fit: BoxFit.contain,
|
|
loadingBuilder: (context, child, loadingProgress) {
|
|
if (loadingProgress == null) return child;
|
|
return const Center(child: CircularProgressIndicator());
|
|
},
|
|
errorBuilder: (context, error, stackTrace) {
|
|
return const Center(child: Text('图片加载失败', style: TextStyle(color: Colors.white)));
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildReplaceButton() {
|
|
return Container(
|
|
height: 32,
|
|
width: 80,
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(8),
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
const Color(0xff80DAA4).withOpacity(0.2),
|
|
const Color(0xff79DDED).withOpacity(0.2),
|
|
],
|
|
),
|
|
border: Border.all(
|
|
color: const Color(0xff80DAA4),
|
|
width: 1,
|
|
),
|
|
),
|
|
child: ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.transparent,
|
|
elevation: 0,
|
|
padding: EdgeInsets.zero,
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
|
),
|
|
),
|
|
onPressed: () async {
|
|
final List<AssetEntity>? result = await AssetPicker.pickAssets(
|
|
context,
|
|
pickerConfig: const AssetPickerConfig(
|
|
maxAssets: 1,
|
|
themeColor: Color(0xff7CDBC8),
|
|
textDelegate: AssetPickerTextDelegate(),
|
|
),
|
|
);
|
|
if (result != null && result.isNotEmpty) {
|
|
widget.onReplace(result.first);
|
|
if (mounted) {
|
|
Navigator.of(context).pop();
|
|
}
|
|
}
|
|
},
|
|
child: const Text(
|
|
"替换素材",
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 14,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} |