Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-02-16 15:35:15 +08:00
parent fa85ae47ac
commit b978ff5649
8 changed files with 101 additions and 78 deletions

View File

@@ -0,0 +1,21 @@
import 'package:flutter/material.dart';
class ColoredBoxTransition extends AnimatedWidget {
const ColoredBoxTransition({
super.key,
required this.color,
this.child,
}) : super(listenable: color);
final Animation<Color?> color;
final Widget? child;
@override
Widget build(BuildContext context) {
return ColoredBox(
color: color.value!,
child: child,
);
}
}

View File

@@ -17,6 +17,7 @@
import 'dart:io' show File, Platform;
import 'package:PiliPlus/common/widgets/colored_box_transition.dart';
import 'package:PiliPlus/common/widgets/flutter/page/page_view.dart';
import 'package:PiliPlus/common/widgets/gesture/image_horizontal_drag_gesture_recognizer.dart';
import 'package:PiliPlus/common/widgets/gesture/image_tap_gesture_recognizer.dart';
@@ -52,7 +53,7 @@ class GalleryViewer extends StatefulWidget {
this.maxScale = 8.0,
required this.quality,
required this.sources,
this.initIndex = 1,
this.initIndex = 0,
});
final double minScale;
@@ -87,14 +88,12 @@ class _GalleryViewerState extends State<GalleryViewer>
late final LongPressGestureRecognizer _longPressGestureRecognizer;
late final AnimationController _animateController;
late final Animation<Decoration> _opacityAnimation;
late final Animation<Color?> _opacityAnimation;
double dx = 0, dy = 0;
Offset _offset = Offset.zero;
bool _dragging = false;
bool get _isActive => _dragging || _animateController.isAnimating;
String _getActualUrl(String url) {
return _quality != 100
? ImageUtils.thumbnailUrl(url, _quality)
@@ -138,14 +137,16 @@ class _GalleryViewerState extends State<GalleryViewer>
});
_animateController = AnimationController(
duration: const Duration(milliseconds: 300),
duration: const Duration(
milliseconds: 750,
), // reverse only if value <= 0.2
vsync: this,
);
_opacityAnimation = _animateController.drive(
DecorationTween(
begin: const BoxDecoration(color: Colors.black),
end: const BoxDecoration(color: Colors.transparent),
ColorTween(
begin: Colors.black,
end: Colors.transparent,
),
);
}
@@ -189,7 +190,7 @@ class _GalleryViewerState extends State<GalleryViewer>
}
void _onDragUpdate(ScaleUpdateDetails details) {
if (!_isActive || _animateController.isAnimating) {
if (!_dragging || _animateController.isAnimating) {
return;
}
@@ -202,16 +203,12 @@ class _GalleryViewerState extends State<GalleryViewer>
}
void _onDragEnd(ScaleEndDetails details) {
if (!_isActive || _animateController.isAnimating) {
if (!_dragging || _animateController.isAnimating) {
return;
}
_dragging = false;
if (_animateController.isCompleted) {
return;
}
if (!_animateController.isDismissed) {
if (_animateController.value > 0.2) {
Get.back();
@@ -256,37 +253,35 @@ class _GalleryViewerState extends State<GalleryViewer>
return Listener(
behavior: .opaque,
onPointerDown: _onPointerDown,
child: DecoratedBoxTransition(
decoration: _opacityAnimation,
child: Stack(
fit: .expand,
alignment: .center,
clipBehavior: .none,
children: [
LayoutBuilder(
builder: (context, constraints) {
_containerSize = constraints.biggest;
return MatrixTransition(
alignment: .topLeft,
animation: _animateController,
onTransform: _onTransform,
child: PageView<ImageHorizontalDragGestureRecognizer>.builder(
controller: _pageController,
onPageChanged: _onPageChanged,
physics: const CustomTabBarViewScrollPhysics(
parent: AlwaysScrollableScrollPhysics(),
),
itemCount: widget.sources.length,
itemBuilder: _itemBuilder,
horizontalDragGestureRecognizer: () =>
_horizontalDragGestureRecognizer,
child: Stack(
fit: .expand,
alignment: .center,
clipBehavior: .none,
children: [
ColoredBoxTransition(color: _opacityAnimation),
LayoutBuilder(
builder: (context, constraints) {
_containerSize = constraints.biggest;
return MatrixTransition(
alignment: .topLeft,
animation: _animateController,
onTransform: _onTransform,
child: PageView<ImageHorizontalDragGestureRecognizer>.builder(
controller: _pageController,
onPageChanged: _onPageChanged,
physics: const CustomTabBarViewScrollPhysics(
parent: AlwaysScrollableScrollPhysics(),
),
);
},
),
_buildIndicator,
],
),
itemCount: widget.sources.length,
itemBuilder: _itemBuilder,
horizontalDragGestureRecognizer: () =>
_horizontalDragGestureRecognizer,
),
);
},
),
_buildIndicator,
],
),
);
}

View File

@@ -77,10 +77,26 @@ class _ViewerState extends State<Viewer> with SingleTickerProviderStateMixin {
_GestureType? _gestureType;
final Matrix4 _matrix = Matrix4.identity();
late double __scale;
double get _scale => __scale;
set _scale(double value) {
__scale = value;
_matrix[0] = _matrix[5] = _matrix[10] = value;
}
late Offset __position;
Offset get _position => __position;
set _position(Offset value) {
__position = value;
_matrix
..[12] = value.dx
..[13] = value.dy;
}
Offset? _scalePos;
late double _scale;
double? _scaleStart;
late Offset _position;
Offset? _referenceFocalPoint;
late Size _imageSize;
@@ -97,10 +113,6 @@ class _ViewerState extends State<Viewer> with SingleTickerProviderStateMixin {
late double _scaleFrom, _scaleTo;
late Offset _positionFrom, _positionTo;
Matrix4 get _matrix =>
Matrix4.translationValues(_position.dx, _position.dy, 0.0)
..scaleByDouble(_scale, _scale, _scale, 1.0);
void _listener() {
final t = Curves.easeOut.transform(_animationController.value);
_scale = t.lerp(_scaleFrom, _scaleTo);
@@ -396,7 +408,7 @@ class _ViewerState extends State<Viewer> with SingleTickerProviderStateMixin {
onPointerDown: _onPointerDown,
onPointerPanZoomStart: _onPointerPanZoomStart,
onPointerSignal: _onPointerSignal,
child: ClipRRect(
child: ClipRect(
child: Transform(
transform: _matrix,
child: widget.child,