feat(mobile): inline asset details (#25952)

The existing implementation for showing asset details uses a bottom
sheet, and is not in sync with the preview or scroll intent. Other apps
use inline details, which is much cleaner and feels better to use.
This commit is contained in:
Thomas
2026-02-17 15:24:34 +00:00
committed by GitHub
parent 06d487782e
commit 5c6433b4ca
42 changed files with 1518 additions and 1277 deletions

View File

@@ -257,6 +257,7 @@ class PhotoView extends StatefulWidget {
this.onDragStart,
this.onDragEnd,
this.onDragUpdate,
this.onDragCancel,
this.onScaleEnd,
this.onLongPressStart,
this.customSize,
@@ -299,6 +300,7 @@ class PhotoView extends StatefulWidget {
this.onDragStart,
this.onDragEnd,
this.onDragUpdate,
this.onDragCancel,
this.onScaleEnd,
this.onLongPressStart,
this.customSize,
@@ -417,6 +419,9 @@ class PhotoView extends StatefulWidget {
/// location.
final PhotoViewImageDragUpdateCallback? onDragUpdate;
/// A callback when a drag gesture is canceled by the system.
final VoidCallback? onDragCancel;
/// A pointer that will trigger a scale has stopped contacting the screen at a
/// particular location.
final PhotoViewImageScaleEndCallback? onScaleEnd;
@@ -543,7 +548,7 @@ class _PhotoViewState extends State<PhotoView> with AutomaticKeepAliveClientMixi
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final computedOuterSize = widget.customSize ?? constraints.biggest;
final backgroundDecoration = widget.backgroundDecoration ?? const BoxDecoration(color: Colors.black);
final backgroundDecoration = widget.backgroundDecoration ?? const BoxDecoration(color: Colors.transparent);
return widget._isCustomChild
? CustomChildWrapper(
@@ -564,6 +569,7 @@ class _PhotoViewState extends State<PhotoView> with AutomaticKeepAliveClientMixi
onDragStart: widget.onDragStart,
onDragEnd: widget.onDragEnd,
onDragUpdate: widget.onDragUpdate,
onDragCancel: widget.onDragCancel,
onScaleEnd: widget.onScaleEnd,
onLongPressStart: widget.onLongPressStart,
outerSize: computedOuterSize,
@@ -596,6 +602,7 @@ class _PhotoViewState extends State<PhotoView> with AutomaticKeepAliveClientMixi
onDragStart: widget.onDragStart,
onDragEnd: widget.onDragEnd,
onDragUpdate: widget.onDragUpdate,
onDragCancel: widget.onDragCancel,
onScaleEnd: widget.onScaleEnd,
onLongPressStart: widget.onLongPressStart,
outerSize: computedOuterSize,

View File

@@ -284,6 +284,7 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {
onDragStart: pageOption.onDragStart,
onDragEnd: pageOption.onDragEnd,
onDragUpdate: pageOption.onDragUpdate,
onDragCancel: pageOption.onDragCancel,
onScaleEnd: pageOption.onScaleEnd,
onLongPressStart: pageOption.onLongPressStart,
gestureDetectorBehavior: pageOption.gestureDetectorBehavior,
@@ -321,6 +322,7 @@ class _PhotoViewGalleryState extends State<PhotoViewGallery> {
onDragStart: pageOption.onDragStart,
onDragEnd: pageOption.onDragEnd,
onDragUpdate: pageOption.onDragUpdate,
onDragCancel: pageOption.onDragCancel,
onScaleEnd: pageOption.onScaleEnd,
onLongPressStart: pageOption.onLongPressStart,
gestureDetectorBehavior: pageOption.gestureDetectorBehavior,
@@ -367,6 +369,7 @@ class PhotoViewGalleryPageOptions {
this.onDragStart,
this.onDragEnd,
this.onDragUpdate,
this.onDragCancel,
this.onScaleEnd,
this.onLongPressStart,
this.gestureDetectorBehavior,
@@ -397,6 +400,7 @@ class PhotoViewGalleryPageOptions {
this.onDragStart,
this.onDragEnd,
this.onDragUpdate,
this.onDragCancel,
this.onScaleEnd,
this.onLongPressStart,
this.gestureDetectorBehavior,
@@ -454,9 +458,12 @@ class PhotoViewGalleryPageOptions {
/// Mirror to [PhotoView.onDragDown]
final PhotoViewImageDragEndCallback? onDragEnd;
/// Mirror to [PhotoView.onDraUpdate]
/// Mirror to [PhotoView.onDragUpdate]
final PhotoViewImageDragUpdateCallback? onDragUpdate;
/// Mirror to [PhotoView.onDragCancel]
final VoidCallback? onDragCancel;
/// Mirror to [PhotoView.onTapDown]
final PhotoViewImageTapDownCallback? onTapDown;

View File

@@ -36,6 +36,7 @@ class PhotoViewCore extends StatefulWidget {
required this.onDragStart,
required this.onDragEnd,
required this.onDragUpdate,
required this.onDragCancel,
required this.onScaleEnd,
required this.onLongPressStart,
required this.gestureDetectorBehavior,
@@ -62,6 +63,7 @@ class PhotoViewCore extends StatefulWidget {
this.onDragStart,
this.onDragEnd,
this.onDragUpdate,
this.onDragCancel,
this.onScaleEnd,
this.onLongPressStart,
this.gestureDetectorBehavior,
@@ -100,6 +102,7 @@ class PhotoViewCore extends StatefulWidget {
final PhotoViewImageDragStartCallback? onDragStart;
final PhotoViewImageDragEndCallback? onDragEnd;
final PhotoViewImageDragUpdateCallback? onDragUpdate;
final VoidCallback? onDragCancel;
final PhotoViewImageLongPressStartCallback? onLongPressStart;
@@ -386,6 +389,7 @@ class PhotoViewCoreState extends State<PhotoViewCore>
onDragUpdate: widget.onDragUpdate != null
? (details) => widget.onDragUpdate!(context, details, widget.controller.value)
: null,
onDragCancel: widget.onDragCancel,
hitDetector: this,
onTapUp: widget.onTapUp != null ? (details) => widget.onTapUp!(context, details, value) : null,
onTapDown: widget.onTapDown != null ? (details) => widget.onTapDown!(context, details, value) : null,

View File

@@ -16,6 +16,7 @@ class PhotoViewGestureDetector extends StatelessWidget {
this.onDragStart,
this.onDragEnd,
this.onDragUpdate,
this.onDragCancel,
this.onLongPressStart,
this.child,
this.onTapUp,
@@ -34,6 +35,7 @@ class PhotoViewGestureDetector extends StatelessWidget {
final GestureDragEndCallback? onDragEnd;
final GestureDragStartCallback? onDragStart;
final GestureDragUpdateCallback? onDragUpdate;
final GestureDragCancelCallback? onDragCancel;
final GestureTapUpCallback? onTapUp;
final GestureTapDownCallback? onTapDown;
@@ -73,7 +75,8 @@ class PhotoViewGestureDetector extends StatelessWidget {
instance
..onStart = onDragStart
..onUpdate = onDragUpdate
..onEnd = onDragEnd;
..onEnd = onDragEnd
..onCancel = onDragCancel;
},
);
}

View File

@@ -28,6 +28,7 @@ class ImageWrapper extends StatefulWidget {
required this.onDragStart,
required this.onDragEnd,
required this.onDragUpdate,
required this.onDragCancel,
required this.onScaleEnd,
required this.onLongPressStart,
required this.outerSize,
@@ -62,6 +63,7 @@ class ImageWrapper extends StatefulWidget {
final PhotoViewImageDragStartCallback? onDragStart;
final PhotoViewImageDragEndCallback? onDragEnd;
final PhotoViewImageDragUpdateCallback? onDragUpdate;
final VoidCallback? onDragCancel;
final PhotoViewImageScaleEndCallback? onScaleEnd;
final PhotoViewImageLongPressStartCallback? onLongPressStart;
final Size outerSize;
@@ -203,6 +205,7 @@ class _ImageWrapperState extends State<ImageWrapper> {
onDragStart: widget.onDragStart,
onDragEnd: widget.onDragEnd,
onDragUpdate: widget.onDragUpdate,
onDragCancel: widget.onDragCancel,
onScaleEnd: widget.onScaleEnd,
onLongPressStart: widget.onLongPressStart,
outerSize: widget.outerSize,
@@ -233,6 +236,7 @@ class _ImageWrapperState extends State<ImageWrapper> {
onDragStart: widget.onDragStart,
onDragEnd: widget.onDragEnd,
onDragUpdate: widget.onDragUpdate,
onDragCancel: widget.onDragCancel,
onScaleEnd: widget.onScaleEnd,
onLongPressStart: widget.onLongPressStart,
gestureDetectorBehavior: widget.gestureDetectorBehavior,
@@ -281,6 +285,7 @@ class CustomChildWrapper extends StatelessWidget {
this.onDragStart,
this.onDragEnd,
this.onDragUpdate,
this.onDragCancel,
this.onScaleEnd,
this.onLongPressStart,
required this.outerSize,
@@ -313,6 +318,7 @@ class CustomChildWrapper extends StatelessWidget {
final PhotoViewImageDragStartCallback? onDragStart;
final PhotoViewImageDragEndCallback? onDragEnd;
final PhotoViewImageDragUpdateCallback? onDragUpdate;
final VoidCallback? onDragCancel;
final PhotoViewImageScaleEndCallback? onScaleEnd;
final PhotoViewImageLongPressStartCallback? onLongPressStart;
final Size outerSize;
@@ -348,6 +354,7 @@ class CustomChildWrapper extends StatelessWidget {
onDragStart: onDragStart,
onDragEnd: onDragEnd,
onDragUpdate: onDragUpdate,
onDragCancel: onDragCancel,
onScaleEnd: onScaleEnd,
onLongPressStart: onLongPressStart,
gestureDetectorBehavior: gestureDetectorBehavior,