Flutter 颤振:覆盖';页面视图';使用child'滚动手势;手势检测器

Flutter 颤振:覆盖';页面视图';使用child'滚动手势;手势检测器,flutter,dart,Flutter,Dart,我在应用程序中使用“底部导航栏”和“页面视图”组合进行导航。用户可以滑动到下一页或使用导航栏 在我的一个页面上,我想使用一个手势检测器来处理垂直和水平平移手势 我找不到一种方法用嵌套的GestureDetector覆盖页面视图的手势检测。这意味着只处理垂直平移手势,因为水平平移手势被页面视图占据 如何在不完全禁用页面浏览量的情况下,仅禁用/覆盖该页面或小部件的页面浏览量手势检测? 我已经创建了我的应用程序的简化版本来隔离这个问题,并在下面附上了这个问题的视频 任何帮助都将不胜感激 以下是my

我在应用程序中使用“底部导航栏”和“页面视图”组合进行导航。用户可以滑动到下一页或使用导航栏

在我的一个页面上,我想使用一个手势检测器来处理垂直和水平平移手势

我找不到一种方法用嵌套的GestureDetector覆盖页面视图的手势检测。这意味着只处理垂直平移手势,因为水平平移手势被页面视图占据

如何在不完全禁用页面浏览量的情况下,仅禁用/覆盖该页面或小部件的页面浏览量手势检测?

我已经创建了我的应用程序的简化版本来隔离这个问题,并在下面附上了这个问题的视频

任何帮助都将不胜感激

以下是my 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),
    );
  }
}
导入“包装:颤振/材料.省道”;
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:GestureIssueExample(),
);
}
}
类GestureIssueExample扩展StatefulWidget{
GestureIssueExample({Key}):super(Key:Key);
@凌驾
_GestureIssueExampleState createState()=>\U GestureIssueExampleState();
}
类_GestureIssueExampleState扩展状态{
国际导航索引;
双左值;
双重价值;
页面控制器_页面控制器;
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:null,
bottomNavigationBar:_buildBottomNavigationBar(),
背景颜色:Colors.white,
正文:页面视图(
控制器:_pageController,
onPageChanged:_onNavigationPageChanged,
儿童:[
//只是一个占位符,表示“刷卡”小部件左侧的页面
_buildSamplePage(“主页”),
//“PageView”的中心子级包含一个处理平移手势的手势检测器
//但是,由于页面视图,仅检测到垂直平移手势,而同时检测到水平和垂直手势
//需要处理。。。
容器(
宽度:MediaQuery.of(context).size.width,
高度:MediaQuery.of(context).size.height,
子:列(
mainAxisAlignment:mainAxisAlignment.center,
crossAxisAlignment:crossAxisAlignment.center,
儿童:[
正文(
“本地X:${uXLocalValue.toString()}\n本地Y:${{uXLocalValue.toString()}”),
手势检测器(
onPanStart:(详细信息)=>setState(
() {
这是.xLocalValue=details.localPosition.dx;
这是._yLocalValue=details.localPosition.dy;
},
),
onPanUpdate:(详细信息)=>setState(
() {
这是.xLocalValue=details.localPosition.dx;
这是._yLocalValue=details.localPosition.dy;
},
),
子:容器(
宽度:MediaQuery.of(context).size.width*0.9,
高度:100.0,
颜色:颜色,红色,
对齐:对齐.center,
子项:文本(“可滑动曲面”,
样式:TextStyle(颜色:Colors.white)),
),
),
],
),
),
//只是一个占位符,表示“刷卡”小部件右侧的页面
_buildSamplePage(“设置”),
],
),
);
}
@凌驾
void initState(){
super.initState();
这是。_navigationIndex=0;
这是。_pageController=pageController(
初始页:_导航索引,
);
}
Widget\u buildSamplePage(字符串文本){
//这只是返回一个填充页面的容器,
//中心有一个文本小部件。
返回容器(
宽度:MediaQuery.of(context).size.width,
高度:MediaQuery.of(context).size.height,
颜色:颜色。灰色[900],
对齐:对齐.center,
子:文本(
文本,
样式:TextStyle(
颜色:Colors.white,fontSize:30.0,fontWeight:fontWeight.bold),
),
);
}
小部件_buildBottomNavigationBar(){
//返回脚手架的底部导航栏
返回底部导航栏(
背景颜色:颜色。灰色[900],
selectedItemColor:Colors.redAccent,
unselectedItemColor:Colors.white,
项目:[
BottomNavigationBarItem(图标:图标(Icons.home),标签:“home”),
底部导航气压计(
图标:图标(图标。复选框\轮廓\空白),标签:“卡片”),
底部导航气压计(
图标:图标(图标。设置),标签:“设置”),
],
当前索引:_导航索引,
onTap:_onNavigationPageChanged,
);
}
void _onNavigationPageChanged(int newIndex){
//为导航栏设置新的导航索引
设置状态(()=>this.\u导航索引=newIndex);
//设置选定页面的动画
_pageController.animateToPage(
新索引,
曲线:Curves.easeInOut,
持续时间:持续时间(微秒:100),
);
}
}

你能试试这样的方法吗:

将此行添加到您的
页面视图中

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

注意:编号
1
是因为带有
gesturedetometer
的页面位于索引
1

你好,Andrej,谢谢你的回答!我已经试过了