Improve the long press to zoom feature.

This commit is contained in:
nyne
2025-03-28 18:03:44 +08:00
parent fddd959545
commit a8e55e0151

View File

@@ -115,6 +115,10 @@ class _GalleryModeState extends State<_GalleryMode>
var imageStates = <State<ComicImage>>{}; var imageStates = <State<ComicImage>>{};
bool isLongPressing = false;
int fingers = 0;
@override @override
void initState() { void initState() {
reader = context.reader; reader = context.reader;
@@ -144,81 +148,103 @@ class _GalleryModeState extends State<_GalleryMode>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return PhotoViewGallery.builder( return Listener(
backgroundDecoration: BoxDecoration( onPointerDown: (event) {
color: context.colorScheme.surface, fingers++;
), },
reverse: reader.mode == ReaderMode.galleryRightToLeft, onPointerUp: (event) {
scrollDirection: reader.mode == ReaderMode.galleryTopToBottom fingers--;
? Axis.vertical },
: Axis.horizontal, onPointerCancel: (event) {
itemCount: totalPages + 2, fingers--;
builder: (BuildContext context, int index) { },
if (index == 0 || index == totalPages + 1) { onPointerMove: (event) {
return PhotoViewGalleryPageOptions.customChild( if (isLongPressing) {
child: const SizedBox(), var controller = photoViewControllers[reader.page]!;
); Offset value = event.delta;
} else { if (isLongPressing) {
int pageIndex = index - 1; controller.updateMultiple(
int startIndex = pageIndex * reader.imagesPerPage; position: controller.position + value,
int endIndex = math.min(
startIndex + reader.imagesPerPage, reader.images!.length);
List<String> pageImages =
reader.images!.sublist(startIndex, endIndex);
cached[index] = true;
cache(index);
photoViewControllers[index] ??= PhotoViewController();
if (reader.imagesPerPage == 1) {
return PhotoViewGalleryPageOptions(
filterQuality: FilterQuality.medium,
controller: photoViewControllers[index],
imageProvider:
_createImageProviderFromKey(pageImages[0], context),
fit: BoxFit.contain,
errorBuilder: (_, error, s, retry) {
return NetworkError(message: error.toString(), retry: retry);
},
); );
} }
return PhotoViewGalleryPageOptions.customChild(
controller: photoViewControllers[index],
minScale: PhotoViewComputedScale.contained * 1.0,
maxScale: PhotoViewComputedScale.covered * 10.0,
child: buildPageImages(pageImages),
);
} }
}, },
pageController: controller, child: PhotoViewGallery.builder(
loadingBuilder: (context, event) => Center( backgroundDecoration: BoxDecoration(
child: SizedBox( color: context.colorScheme.surface,
width: 20.0, ),
height: 20.0, reverse: reader.mode == ReaderMode.galleryRightToLeft,
child: CircularProgressIndicator( scrollDirection: reader.mode == ReaderMode.galleryTopToBottom
backgroundColor: context.colorScheme.surfaceContainerHigh, ? Axis.vertical
value: event == null || event.expectedTotalBytes == null : Axis.horizontal,
? null itemCount: totalPages + 2,
: event.cumulativeBytesLoaded / event.expectedTotalBytes!, builder: (BuildContext context, int index) {
if (index == 0 || index == totalPages + 1) {
return PhotoViewGalleryPageOptions.customChild(
child: const SizedBox(),
);
} else {
int pageIndex = index - 1;
int startIndex = pageIndex * reader.imagesPerPage;
int endIndex = math.min(
startIndex + reader.imagesPerPage, reader.images!.length);
List<String> pageImages =
reader.images!.sublist(startIndex, endIndex);
cached[index] = true;
cache(index);
photoViewControllers[index] ??= PhotoViewController();
if (reader.imagesPerPage == 1) {
return PhotoViewGalleryPageOptions(
filterQuality: FilterQuality.medium,
controller: photoViewControllers[index],
imageProvider:
_createImageProviderFromKey(pageImages[0], context),
fit: BoxFit.contain,
errorBuilder: (_, error, s, retry) {
return NetworkError(message: error.toString(), retry: retry);
},
);
}
return PhotoViewGalleryPageOptions.customChild(
controller: photoViewControllers[index],
minScale: PhotoViewComputedScale.contained * 1.0,
maxScale: PhotoViewComputedScale.covered * 10.0,
child: buildPageImages(pageImages),
);
}
},
pageController: controller,
loadingBuilder: (context, event) => Center(
child: SizedBox(
width: 20.0,
height: 20.0,
child: CircularProgressIndicator(
backgroundColor: context.colorScheme.surfaceContainerHigh,
value: event == null || event.expectedTotalBytes == null
? null
: event.cumulativeBytesLoaded / event.expectedTotalBytes!,
),
), ),
), ),
onPageChanged: (i) {
if (i == 0) {
if (reader.isFirstChapterOfGroup || !reader.toPrevChapter()) {
reader.toPage(1);
}
} else if (i == totalPages + 1) {
if (reader.isLastChapterOfGroup || !reader.toNextChapter()) {
reader.toPage(totalPages);
}
} else {
reader.setPage(i);
context.readerScaffold.update();
}
},
), ),
onPageChanged: (i) {
if (i == 0) {
if (reader.isFirstChapterOfGroup || !reader.toPrevChapter()) {
reader.toPage(1);
}
} else if (i == totalPages + 1) {
if (reader.isLastChapterOfGroup || !reader.toNextChapter()) {
reader.toPage(totalPages);
}
} else {
reader.setPage(i);
context.readerScaffold.update();
}
},
); );
} }
@@ -266,7 +292,7 @@ class _GalleryModeState extends State<_GalleryMode>
} else { } else {
imageWidgets = images.map((imageKey) { imageWidgets = images.map((imageKey) {
ImageProvider imageProvider = ImageProvider imageProvider =
_createImageProviderFromKey(imageKey, context); _createImageProviderFromKey(imageKey, context);
return Expanded( return Expanded(
child: ComicImage( child: ComicImage(
image: imageProvider, image: imageProvider,
@@ -312,7 +338,7 @@ class _GalleryModeState extends State<_GalleryMode>
@override @override
void handleLongPressDown(Offset location) { void handleLongPressDown(Offset location) {
if (!appdata.settings['enableLongPressToZoom']) { if (!appdata.settings['enableLongPressToZoom'] || fingers != 1) {
return; return;
} }
var photoViewController = photoViewControllers[reader.page]!; var photoViewController = photoViewControllers[reader.page]!;
@@ -322,16 +348,18 @@ class _GalleryModeState extends State<_GalleryMode>
target, target,
Offset(size.width / 2 - location.dx, size.height / 2 - location.dy), Offset(size.width / 2 - location.dx, size.height / 2 - location.dy),
); );
isLongPressing = true;
} }
@override @override
void handleLongPressUp(Offset location) { void handleLongPressUp(Offset location) {
if (!appdata.settings['enableLongPressToZoom']) { if (!appdata.settings['enableLongPressToZoom'] || !isLongPressing) {
return; return;
} }
var photoViewController = photoViewControllers[reader.page]!; var photoViewController = photoViewControllers[reader.page]!;
double target = photoViewController.getInitialScale!.call()!; double target = photoViewController.getInitialScale!.call()!;
photoViewController.animateScale?.call(target); photoViewController.animateScale?.call(target);
isLongPressing = false;
} }
Timer? keyRepeatTimer; Timer? keyRepeatTimer;