简体   繁体   English

Flutter:用孩子的 GestureDetector 覆盖“PageView”滚动手势

[英]Flutter: Override 'PageView' scroll gesture with child's GestureDetector

I am using a combination of "BottomNavigationBar" and "PageView" for navigation in my app.我在我的应用程序中使用“BottomNavigationBar”和“PageView”的组合进行导航。 The user can either swipe to the next page or use the navigation bar.用户可以滑动到下一页或使用导航栏。

On one of my pages, I would like to use a gesture detector that handles pan gestures, both vertically and horizontally.在我的一个页面上,我想使用一个手势检测器来处理垂直和水平平移手势。

I can't find a way to override the PageView's gesture detection with the nested GestureDetector.我找不到用嵌套的 GestureDetector 覆盖 PageView 的手势检测的方法。 This means only vertical pan gestures are handled, as the horizontal ones are occupied by the PageView.这意味着只处理垂直平移手势,因为 PageView 占据了水平手势。

How can I disable / override the PageViews gesture detection for only that page or only the widget, without completely disabling the PageViews scroll physics?如何禁用/覆盖仅针对该页面或仅小部件的 PageViews 手势检测,而不完全禁用 PageViews 滚动物理?

I have created a simplified version of my App to isolate the issue, and attached a video of the problem below.我创建了我的应用程序的简化版本来隔离问题,并在下面附上了问题的视频。

Any help would be greatly appreciated!任何帮助将不胜感激!

“GestureDetector”只接收垂直拖动手势......

Here is the code inside my main.dart:这是我的 main.dart 中的代码:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: GestureIssueExample(),
    );
  }
}

class GestureIssueExample extends StatefulWidget {
  GestureIssueExample({Key key}) : super(key: key);

  @override
  _GestureIssueExampleState createState() => _GestureIssueExampleState();
}

class _GestureIssueExampleState extends State<GestureIssueExample> {
  int _navigationIndex;
  double _xLocalValue;
  double _yLocalValue;
  PageController _pageController;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: null,
      bottomNavigationBar: _buildBottomNavigationBar(),
      backgroundColor: Colors.white,
      body: PageView(
        controller: _pageController,
        onPageChanged: _onNavigationPageChanged,
        children: [
          //Just a placeholder to represent a page to the left of the "swipe cards" widget
          _buildSamplePage("Home"),

          //Center child of 'PageView', contains a GestureDetector that handles Pan Gestures
          //Thanks to the page view however, only vertical pan gestures are detected, while both horizontal and vertical gestures
          //need to be handled...
          Container(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Text(
                    "Local X: ${_xLocalValue.toString()}\nLocal Y: ${_yLocalValue.toString()}"),
                GestureDetector(
                  onPanStart: (details) => setState(
                    () {
                      this._xLocalValue = details.localPosition.dx;
                      this._yLocalValue = details.localPosition.dy;
                    },
                  ),
                  onPanUpdate: (details) => setState(
                    () {
                      this._xLocalValue = details.localPosition.dx;
                      this._yLocalValue = details.localPosition.dy;
                    },
                  ),
                  child: Container(
                    width: MediaQuery.of(context).size.width * 0.9,
                    height: 100.0,
                    color: Colors.red,
                    alignment: Alignment.center,
                    child: Text("Slidable Surface",
                        style: TextStyle(color: Colors.white)),
                  ),
                ),
              ],
            ),
          ),

          //Just a placeholder to represent a page to the right of the "swipe cards" widget
          _buildSamplePage("Settings"),
        ],
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    this._navigationIndex = 0;
    this._pageController = PageController(
      initialPage: _navigationIndex,
    );
  }

  Widget _buildSamplePage(String text) {
    // This simply returns a container that fills the page,
    // with a text widget in its center.

    return Container(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height,
      color: Colors.grey[900],
      alignment: Alignment.center,
      child: Text(
        text,
        style: TextStyle(
            color: Colors.white, fontSize: 30.0, fontWeight: FontWeight.bold),
      ),
    );
  }

  Widget _buildBottomNavigationBar() {
    //Returns the bottom navigation bar for the scaffold
    return BottomNavigationBar(
      backgroundColor: Colors.grey[900],
      selectedItemColor: Colors.redAccent,
      unselectedItemColor: Colors.white,
      items: [
        BottomNavigationBarItem(icon: Icon(Icons.home_outlined), label: "Home"),
        BottomNavigationBarItem(
            icon: Icon(Icons.check_box_outline_blank), label: "Cards"),
        BottomNavigationBarItem(
            icon: Icon(Icons.settings_outlined), label: "Settings"),
      ],
      currentIndex: _navigationIndex,
      onTap: _onNavigationPageChanged,
    );
  }

  void _onNavigationPageChanged(int newIndex) {
    //Set the new navigation index for the nav bar
    setState(() => this._navigationIndex = newIndex);

    //Animate to the selected page
    _pageController.animateToPage(
      newIndex,
      curve: Curves.easeInOut,
      duration: Duration(microseconds: 100),
    );
  }
}

Can you try something like this:你可以尝试这样的事情:

Add this line to your PageView :将此行添加到您的PageView

PageView(
...
physics: _navigationIndex == 1 ? NeverScrollableScrollPhysics() : AlwaysScrollableScrollPhysics(),
...
)

Note: the number 1 is because the page with the GestureDetector is on index 1 .注意:数字1是因为带有GestureDetector的页面位于索引1上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 问题 GestureDetector onTapDown with PageView flutter - problem GestureDetector onTapDown with PageView flutter Flutter 多次调用 Setstate(GestureDetector 和 PageView) - Flutter Setstate called multiple times (GestureDetector & PageView) Flutter GestureDetector 不捕获手势,如果它的孩子正在处理它们 - Flutter GestureDetector is not capturing gestures if it's child is handling them 如何在 GestureDetector 中捕捉其孩子的手势? - How to catch gesture from its child in GestureDetector? 在 Flutter 中如何让 PageView 滚动得更快? 动画似乎很慢,内部 ListView 无法响应我的垂直手势 - In Flutter how to make PageView scroll faster? The animation seems to be slow and the inner ListView cant response my vertical gesture Flutter 在另一个 PageView 内阻止 PageView 滚动 - Flutter block scroll of PageView inside another PageView Flutter:有没有办法在用户滚动另一个 pageView 时以编程方式滚动 pageView? - Flutter: Is there way to scroll pageView programmatically while user scroll another pageView? 颤振:我如何将手势从 GestureDetector 传递给孩子? - flutter: How I can pass gesture to children from GestureDetector? 如何防止点击 GestureDetector child Flutter - How to prevent clicking on GestureDetector child Flutter 如何在 Flutter 中使 GestureDetector 被孩子阻止 - How to make GestureDetector blocked by child in Flutter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM