mod: 图片质量

This commit is contained in:
guozhigq
2023-08-05 21:12:29 +08:00
parent 90c617a1a4
commit 8d7ddcc5cd
10 changed files with 193 additions and 179 deletions

View File

@ -43,7 +43,7 @@ class LiveCard extends StatelessWidget {
Hero(
tag: heroTag,
child: NetworkImgLayer(
src: liveItem.cover + '@.webp',
src: liveItem.cover,
type: 'emote',
width: maxWidth,
height: maxHeight,

View File

@ -11,6 +11,7 @@ class NetworkImgLayer extends StatelessWidget {
final String? type;
final Duration? fadeOutDuration;
final Duration? fadeInDuration;
final int? quality;
const NetworkImgLayer({
Key? key,
@ -22,6 +23,8 @@ class NetworkImgLayer extends StatelessWidget {
this.type,
this.fadeOutDuration,
this.fadeInDuration,
// 图片质量 默认1%
this.quality = 1,
}) : super(key: key);
@override
@ -37,7 +40,8 @@ class NetworkImgLayer extends StatelessWidget {
? 0
: StyleString.imgRadius.x),
child: CachedNetworkImage(
imageUrl: src!.startsWith('//') ? 'https:${src!}' : src!,
imageUrl:
'${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality}q.webp',
width: width ?? double.infinity,
height: height ?? double.infinity,
alignment: Alignment.center,

View File

@ -76,7 +76,7 @@ class VideoCardH extends StatelessWidget {
Hero(
tag: heroTag,
child: NetworkImgLayer(
src: videoItem.pic + '@.webp',
src: videoItem.pic,
width: maxWidth,
height: maxHeight,
),

View File

@ -69,7 +69,7 @@ class VideoCardV extends StatelessWidget {
Hero(
tag: heroTag,
child: NetworkImgLayer(
src: videoItem.pic + '@.webp',
src: videoItem.pic,
width: maxWidth,
height: maxHeight,
),

View File

@ -42,7 +42,7 @@ class FavItem extends StatelessWidget {
return Hero(
tag: heroTag,
child: NetworkImgLayer(
src: favFolderItem.cover + '@.webp',
src: favFolderItem.cover,
width: maxWidth,
height: maxHeight,
),

View File

@ -74,7 +74,7 @@ class FavVideoCardH extends StatelessWidget {
Hero(
tag: heroTag,
child: NetworkImgLayer(
src: videoItem.pic + '@.webp',
src: videoItem.pic,
width: maxWidth,
height: maxHeight,
),

View File

@ -82,9 +82,8 @@ class HistoryItem extends StatelessWidget {
tag: heroTag,
child: NetworkImgLayer(
src: (videoItem.cover != ''
? videoItem.cover
: videoItem.covers.first) +
'@.webp',
? videoItem.cover
: videoItem.covers.first),
width: maxWidth,
height: maxHeight,
),

View File

@ -65,7 +65,7 @@ class LiveCardV extends StatelessWidget {
Hero(
tag: heroTag,
child: NetworkImgLayer(
src: '${liveItem.cover!}@.webp',
src: liveItem.cover!,
width: maxWidth,
height: maxHeight,
),

View File

@ -1,6 +1,7 @@
// ignore_for_file: library_private_types_in_public_api
import 'package:dismissible_page/dismissible_page.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:extended_image/extended_image.dart';
@ -44,179 +45,189 @@ class _ImagePreviewState extends State<ImagePreview>
@override
Widget build(BuildContext context) {
return Stack(
children: [
DismissiblePage(
backgroundColor: Colors.transparent,
onDismissed: () {
Navigator.of(context).pop();
},
// Note that scrollable widget inside DismissiblePage might limit the functionality
// If scroll direction matches DismissiblePage direction
direction: DismissiblePageDismissDirection.down,
disabled: _dismissDisabled,
isFullScreen: true,
child: Hero(
tag: _previewController
.imgList[_previewController.initialPage.value],
child: GestureDetector(
onTap: () {
_previewController.visiable = !_previewController.visiable;
setState(() {});
},
child: ExtendedImageGesturePageView.builder(
controller: ExtendedPageController(
initialPage: _previewController.initialPage.value,
pageSpacing: 0,
),
onPageChanged: (int index) {
_previewController.initialPage.value = index;
_previewController.currentPage.value = index + 1;
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
primary: false,
toolbarHeight: 0,
backgroundColor: Colors.black,
systemOverlayStyle: SystemUiOverlayStyle.light,
),
body: Stack(
children: [
DismissiblePage(
backgroundColor: Colors.transparent,
onDismissed: () {
Navigator.of(context).pop();
},
// Note that scrollable widget inside DismissiblePage might limit the functionality
// If scroll direction matches DismissiblePage direction
direction: DismissiblePageDismissDirection.down,
disabled: _dismissDisabled,
isFullScreen: true,
child: Hero(
tag: _previewController
.imgList[_previewController.initialPage.value],
child: GestureDetector(
onTap: () {
_previewController.visiable = !_previewController.visiable;
setState(() {});
},
canScrollPage: (GestureDetails? gestureDetails) =>
gestureDetails!.totalScale! <= 1.0,
preloadPagesCount: 2,
itemCount: _previewController.imgList.length,
itemBuilder: (BuildContext context, int index) {
return ExtendedImage.network(
_previewController.imgList[index],
fit: BoxFit.contain,
mode: ExtendedImageMode.gesture,
onDoubleTap: (ExtendedImageGestureState state) {
final Offset? pointerDownPosition =
state.pointerDownPosition;
final double? begin = state.gestureDetails!.totalScale;
double end;
//remove old
_doubleClickAnimation
?.removeListener(_doubleClickAnimationListener);
//stop pre
_doubleClickAnimationController.stop();
//reset to use
_doubleClickAnimationController.reset();
if (begin == doubleTapScales[0]) {
setState(() {
_dismissDisabled = true;
});
end = doubleTapScales[1];
} else {
setState(() {
_dismissDisabled = false;
});
end = doubleTapScales[0];
}
_doubleClickAnimationListener = () {
state.handleDoubleTap(
scale: _doubleClickAnimation!.value,
doubleTapPosition: pointerDownPosition);
};
_doubleClickAnimation = _doubleClickAnimationController
.drive(Tween<double>(begin: begin, end: end));
_doubleClickAnimation!
.addListener(_doubleClickAnimationListener);
_doubleClickAnimationController.forward();
},
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
final ImageChunkEvent? loadingProgress =
state.loadingProgress;
final double? progress =
loadingProgress?.expectedTotalBytes != null
? loadingProgress!.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null;
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
width: 150.0,
child: LinearProgressIndicator(value: progress),
),
const SizedBox(height: 10.0),
Text('${((progress ?? 0.0) * 100).toInt()}%'),
],
),
);
}
},
initGestureConfigHandler: (ExtendedImageState state) {
return GestureConfig(
inPageView: true,
initialScale: 1.0,
maxScale: 5.0,
animationMaxScale: 6.0,
initialAlignment: InitialAlignment.center,
);
},
);
},
),
),
),
),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
// height: 45,
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom, top: 20),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[
Colors.transparent,
Colors.black87,
],
tileMode: TileMode.mirror,
),
),
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Obx(
() => Text.rich(
TextSpan(
style: const TextStyle(
color: Colors.white, fontSize: 18),
children: [
TextSpan(
text:
_previewController.currentPage.toString()),
const TextSpan(text: ' / '),
TextSpan(
text: _previewController.imgList.length
.toString()),
]),
),
child: ExtendedImageGesturePageView.builder(
controller: ExtendedPageController(
initialPage: _previewController.initialPage.value,
pageSpacing: 0,
),
const Spacer(),
ElevatedButton(
onPressed: () => _previewController.onShareImg(),
child: const Text('分享')),
const SizedBox(width: 10),
ElevatedButton(
onPressed: () => _previewController.onSaveImg(),
child: const Text('保存'))
],
onPageChanged: (int index) {
_previewController.initialPage.value = index;
_previewController.currentPage.value = index + 1;
},
canScrollPage: (GestureDetails? gestureDetails) =>
gestureDetails!.totalScale! <= 1.0,
preloadPagesCount: 2,
itemCount: _previewController.imgList.length,
itemBuilder: (BuildContext context, int index) {
return ExtendedImage.network(
_previewController.imgList[index],
fit: BoxFit.contain,
mode: ExtendedImageMode.gesture,
onDoubleTap: (ExtendedImageGestureState state) {
final Offset? pointerDownPosition =
state.pointerDownPosition;
final double? begin = state.gestureDetails!.totalScale;
double end;
//remove old
_doubleClickAnimation
?.removeListener(_doubleClickAnimationListener);
//stop pre
_doubleClickAnimationController.stop();
//reset to use
_doubleClickAnimationController.reset();
if (begin == doubleTapScales[0]) {
setState(() {
_dismissDisabled = true;
});
end = doubleTapScales[1];
} else {
setState(() {
_dismissDisabled = false;
});
end = doubleTapScales[0];
}
_doubleClickAnimationListener = () {
state.handleDoubleTap(
scale: _doubleClickAnimation!.value,
doubleTapPosition: pointerDownPosition);
};
_doubleClickAnimation = _doubleClickAnimationController
.drive(Tween<double>(begin: begin, end: end));
_doubleClickAnimation!
.addListener(_doubleClickAnimationListener);
_doubleClickAnimationController.forward();
},
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
final ImageChunkEvent? loadingProgress =
state.loadingProgress;
final double? progress =
loadingProgress?.expectedTotalBytes != null
? loadingProgress!.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null;
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
width: 150.0,
child:
LinearProgressIndicator(value: progress),
),
const SizedBox(height: 10.0),
Text('${((progress ?? 0.0) * 100).toInt()}%'),
],
),
);
}
},
initGestureConfigHandler: (ExtendedImageState state) {
return GestureConfig(
inPageView: true,
initialScale: 1.0,
maxScale: 5.0,
animationMaxScale: 6.0,
initialAlignment: InitialAlignment.center,
);
},
);
},
),
),
),
),
),
],
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Container(
// height: 45,
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).padding.bottom, top: 20),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[
Colors.transparent,
Colors.black87,
],
tileMode: TileMode.mirror,
),
),
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Obx(
() => Text.rich(
TextSpan(
style: const TextStyle(
color: Colors.white, fontSize: 18),
children: [
TextSpan(
text: _previewController.currentPage
.toString()),
const TextSpan(text: ' / '),
TextSpan(
text: _previewController.imgList.length
.toString()),
]),
),
),
const Spacer(),
ElevatedButton(
onPressed: () => _previewController.onShareImg(),
child: const Text('分享')),
const SizedBox(width: 10),
ElevatedButton(
onPressed: () => _previewController.onSaveImg(),
child: const Text('保存'))
],
),
),
),
),
],
),
);
}
}

View File

@ -49,7 +49,7 @@ Widget searchLivePanel(BuildContext context, ctr, list) {
Hero(
tag: Utils.makeHeroTag(i.roomid),
child: NetworkImgLayer(
src: i.cover + '@.webp',
src: i.cover,
type: 'emote',
width: maxWidth,
height: maxHeight,