【Flutter】PageViewとInteractiveViewerのジェスチャーの競合を解消したい。

私のFlutterアプリケーションでは、PageViewInteractiveViewerの両方を使用して画像を表示および操作しています。InteractiveViewerを使用して画像をズームインした後、画像をドラッグしようとすると、ページがすぐに切り替わる問題に遭遇しました。この挙動は、PageViewInteractiveViewerのジェスチャーが競合しているためのように思われます。
PageViewには元々ズームイン/アウトの機能がありますが、どこをタップしても中央しか拡大されないため、InteractiveViewerを併用する形をとっています。https://github.com/bluefireteam/photo_view/issues/538)

試したこと:

  • 両方のウィジェットのジェスチャーを調査して、一方を他方よりも優先する方法がないかを探しました。
  • 以下のStackOverflowの投稿を確認しました。これは、画像がズームインされていない場合にのみページングを実行することを提案しています:https://stackoverflow.com/questions/64748389/interactiveviewer-inside-pageview。しかし、これの動作は望ましくありません。

期待する挙動: 画像がズームインされている場合でも、ズームインされた画像の端までドラッグした場合にのみ、アプリケーションが次のページに切り替わるようにしたいです。

現在の挙動: 現在、ズームインした後、ドラッグジェスチャーでページがすぐに切り替わります。

このジェスチャーの競合を処理するための提案や解決策があれば嬉しいです。

コード:
(画像URLは著作権フリーのものを使用しています)

Dart

1import 'dart:developer';2import 'package:flutter/material.dart';3 4void main() => runApp(const MyApp());5 6class MyApp extends StatelessWidget {7 const MyApp({super.key});8 9 10 Widget build(BuildContext context) {11 return MaterialApp(12 title: 'PhotoView + Interactiveviewer',13 theme: ThemeData(14 primarySwatch: Colors.blue,15 ),16 home: const GalleryExample(),17 );18 }19}20 21class GalleryExample extends StatefulWidget {22 const GalleryExample({super.key});23 24 25 _GalleryExampleState createState() => _GalleryExampleState();26}27 28class _GalleryExampleState extends State<GalleryExample> {29 late int selectedIndex;30 final TransformationController _transformationController = TransformationController();31 late TapDownDetails _doubleTapDetails;32 33 List<String> pageItems = [34 "https://user0514.cdnw.net/shared/img/thumb/12redsugar721_TP_V.jpg",35 "https://user0514.cdnw.net/shared/img/thumb/05redsugar721_TP_V.jpg"36 ];37 38 void _handleDoubleTap() {39 print("double tap");40 final currentScale = _transformationController.value.getMaxScaleOnAxis();41 if (currentScale > 1.0) {42 _transformationController.value = Matrix4.identity();43 } else {44 final position = _doubleTapDetails.localPosition;45 _transformationController.value = Matrix4.identity()46 ..translate(-position.dx, -position.dy)47 ..scale(2.0);48 }49 }50 51 52 void initState() {53 super.initState();54 selectedIndex = 0;55 }56 57 58 Widget build(59 BuildContext context,60 ) {61 return Scaffold(62 backgroundColor: Colors.black,63 body: GestureDetector(64 behavior: HitTestBehavior.opaque,65 child: SafeArea(66 child: Stack(67 children: [68 Container(69 color: Colors.black,70 child: PageView.builder(71 pageSnapping: true,72 reverse: true,73 itemCount: pageItems.length,74 itemBuilder: (context, index) {75 return LayoutBuilder(76 builder: (BuildContext context, BoxConstraints constraints) {77 return InteractiveViewer(78 maxScale: 5.0,79 minScale: 1.0,80 transformationController: _transformationController,81 onInteractionEnd: (details) {82 if (_transformationController.value.getMaxScaleOnAxis() == 1.0) {83 _transformationController.value = Matrix4.identity();84 }85 },86 child: GestureDetector(87 onDoubleTapDown: (details) {88 _doubleTapDetails = details;89 },90 onDoubleTap: _handleDoubleTap,91 child: Image.network(92 pageItems[index],93 fit: BoxFit.contain,94 ),95 ),96 );97 },98 );99 },100 ),101 )102 ],103 ),104 ),105 ));106 }107}

コメントを投稿

0 コメント