2017-05-09 3 views
2

Ich habe eine TabBarView wo jede Registerkarte enthält eine Image in einer GestureDetector zum Zoomen und Schwenken gewickelt. Wenn es darauf ankommt, setze ich gerade den Zoom ein: How do I pan and zoom an image?.GestureDetector in TabBarView - verschachteltes Scrollen?

Jetzt habe ich das Problem, dass Zoomen funktioniert nur, wenn die Quetschbewegung sehr vertikal ist. Wenn ich mehr als ein bisschen aus bin, werden die Berührungsereignisse sofort verwendet, um zur nächsten Registerkarte zu wischen, obwohl ich beide Finger benutze. Und ich nehme an, dass horizontales Schwenken überhaupt nicht funktioniert.

Gibt es einen Mechanismus in Flutter, der es dem inneren GestureDetector erlauben würde, bestimmte Berührungsereignisse (aber nicht andere und nicht immer) abzufangen, bevor sie an die TabBarView übergeben werden?

Antwort

2

Ich denke, Flutter Pan Gestenerkenner sollte wahrscheinlich auf die Skala Gestenerkenner ergeben, wenn es erkennt, dass ein zweiter Zeiger ist unten und eine Skala Geste Erkennung ist aktiv. Fühlen Sie sich frei, ein Problem dafür zu melden, wenn Sie zustimmen.

In der Zwischenzeit können Sie den Pan Gestenerkenner PageView deaktivieren, indem Sie einen undurchsichtigen GestureRecognizer darauf setzen und die Skalierungsereignisse an Ihren Status weiterleiten.

import 'package:flutter/material.dart'; 
import 'package:vector_math/vector_math_64.dart'; 

void main() { 
    runApp(new MyApp()); 
} 

class MyApp extends StatelessWidget { 
    @override 
    Widget build(BuildContext context) { 
    return new MaterialApp(
     title: 'Flutter Demo', 
     home: new MyHomePage(), 
    ); 
    } 
} 

class MyHomePage extends StatelessWidget { 
    MyHomePage({Key key}) : super(key: key); 

    @override 
    Widget build(BuildContext context) { 
    return new DefaultTabController(
     length: 2, 
     child: new Scaffold(
     appBar: new AppBar(
      bottom: new TabBar(
      tabs: [ 
       new Tab(text: 'foo'), 
       new Tab(text: 'bar'), 
      ], 
     ), 
     ), 
     body: new ScalableTabBarView() 
    ), 
    ); 
    } 
} 

class ScalableTabBarView extends StatelessWidget { 

    final List<GlobalKey<ScaledState>> keys = <GlobalKey<ScaledState>>[ 
    new GlobalKey<ScaledState>(), 
    new GlobalKey<ScaledState>(), 
    ]; 

    Widget build(BuildContext context) { 
    return new Stack(children: [ 
     new TabBarView(
     children: [ 
      new Center(
      child: new Scaled(
       child: new FlutterLogo(), 
       key: keys[0], 
      ), 
     ), 
      new Center(
      child: new Scaled(
       child: new FlutterLogo(), 
       key: keys[1], 
      ), 
     ), 
     ], 
    ), 
     new GestureDetector(
     behavior: HitTestBehavior.opaque, 
     onScaleStart: (ScaleStartDetails details) { 
      keys[DefaultTabController.of(context).index].currentState.onScaleStart(details); 
     }, 
     onScaleUpdate: (ScaleUpdateDetails details) { 
      keys[DefaultTabController.of(context).index].currentState.onScaleUpdate(details); 
     }, 
     onScaleEnd: (ScaleEndDetails details) 
     { 
      keys[DefaultTabController.of(context).index].currentState.onScaleEnd(details); 
     } 
    ), 
    ], 
    ); 
    } 
} 

class Scaled extends StatefulWidget { 
    Scaled({ Key key, this.child }) : super(key: key); 

    final Widget child; 
    State createState() => new ScaledState(); 
} 

class ScaledState extends State<Scaled> { 

    double _previousScale; 
    double _scale = 1.0; 

    void onScaleStart(ScaleStartDetails details) { 
    print(details); 
    setState(() { 
     _previousScale = _scale; 
    }); 
    } 
    void onScaleUpdate(ScaleUpdateDetails details) { 
    print(details); 
    setState(() { 
     _scale = _previousScale * details.scale; 
    }); 
    } 
    void onScaleEnd(ScaleEndDetails details) { 
    print(details); 
    setState(() { 
     _previousScale = null; 
    }); 
    } 
    @override 
    Widget build(BuildContext context) { 
    return new GestureDetector(
     child: new Transform(
      transform: new Matrix4.diagonal3(new Vector3(_scale, _scale, _scale)), 
      alignment: FractionalOffset.center, 
      child: widget.child, 
     ), 
    ); 
    } 
} 

Handhabung der Skala Gesten außerhalb der TabBarView kann auch den skalierte Zustand der Registerkarten, anstatt sie, wenn auf 1,0 zurückgesetzt zu erinnern, verwendet werden, wenn sie außerhalb des Bildschirms ist.

+0

Vielen Dank für Ihre Antwort! Ich habe heute früh ein Problem eingereicht, bin aber erst jetzt dazu gekommen, Ihre aktuelle Lösung auszuprobieren. Nur um sicher zu gehen: Dadurch wird die Swiping-Funktionalität der 'TabBarView' vollständig deaktiviert, sodass ich nur durch Klicken auf die' TabBar' Tabs wechseln kann, richtig? Gibt es eine Möglichkeit, Drag-Events an die TabBarView zu "weiterleiten", um sie zum Swipen zu verwenden? –

+0

Vielen Dank für die Einreichung des Problems. Ich weiß leider nicht, wie man die Drag-Events an die TabBarView weiterleiten kann. Wenn dies für Sie wichtig ist, sehen wir, welche Antwort Sie auf das Problem bekommen. –

+0

Hier ist das Problem, das David eingereicht hat, falls jemand anderes es befolgen möchte: https://github.com/flutter/flutter/issues/9949 –

Verwandte Themen