Flutter:当 GestureDetector 中有 ListView 时,它显然不会收到 Drag 事件

问题描述 投票:0回答:2

我错过了什么吗?文档说事件从最里面的子级冒泡到祖先,但下面的代码不会将“拖动”打印到控制台。但它确实打印“点击”。 将 NeverScrollablePhyiscs 应用于 ListView 确实有效,但我想在两个级别上监听该事件。将 HitTestBehavior.translucent 应用于 GestureDetector 不会改变任何内容。

import "package:flutter/material.dart";

void main() => runApp(MyApp());

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

class MyHomePage extends StatelessWidget {
  @override
    Widget build(BuildContext context) {
      return Scaffold(
        body: GestureDetector(
          onVerticalDragUpdate: (DragUpdateDetails details) {
            print("dragged");
          },
          onTap: () {
            print("tapped");
          },
          child: ListView.builder(
            itemBuilder: (context, index) {
              return Container(
                padding: EdgeInsets.all(20.0),
                child: Text(
                  "The GestureDetector above me does not react to drag events. Maybe my parent is at fault?"
                )
              );
            },
          )
        )
      );
    }
}
listview nested flutter gesturedetector
2个回答
18
投票

您可以使用

Listener

监听原始指针事件
      return Scaffold(
            body: Listener(onPointerMove: (opm) {
              print("onPointerMove .. ${opm.position}");
        }, child: ListView.builder(
          itemBuilder: (context, index) {
            return Container(
                padding: EdgeInsets.all(20.0),
                child: Text(
                    "The GestureDetector above me does not react to drag events. Maybe my parent is at fault?"));
          },
        )));

0
投票

Listener
小部件对我来说太原始了,它没有拖动开始/结束事件来从其子
ListView
捕获。有一个
NotificationListener
可以捕获任何祖先冒泡的内容:

child: NotificationListener(
  onNotification: (ScrollNotification notification) {
    if (notification is ScrollEndNotification) {
      log('NotificationListener: ${notification.dragDetails?.primaryVelocity}');
    }

    return false; // keep bubbling up
  },
  child: ListView(
    children: [for (int i = 0; i < 10; i++) _tile(i)],
  ),
),

请注意,如果子组件不是可滚动小部件或者不需要滚动(例如实际的

ListView
但其内容不会浮动在屏幕上),则不会有任何内容冒泡到
NotificationListener
!如果您想捕获所有滚动拖动事件,而不管子内容如何,那么您可能需要同时使用
GestureDetector
(检测不属于祖先的事件)和
NotificationListener
来检测在层次结构中冒泡的事件。

GestureDetector(
  // This will trigger if an ancestor doesn't "win" the event
  onVerticalDragEnd: (DragEndDetails details) {
    log('GestureDetector: ${details.primaryVelocity}');
  },
  child: NotificationListener(
    // This will trigger if an ancestor "wins" the event and bubbles 
    onNotification: (ScrollNotification notification) {
      if (notification is ScrollEndNotification) {
        log('NotificationListener: ${notification.dragDetails?.primaryVelocity}');
      }

      return false; // keep bubbling up
    },
    child: ListView(
      children: [for (int i = 0; i < 10; i++) _tile(i)],
    ),
  ),
),
© www.soinside.com 2019 - 2024. All rights reserved.