在列表视图中滚动地图时如何避免滚动列表视图

dia*_*uid 6 flutter flutter-layout

我有一个 ListView,在它的顶部我有一张地图,我希望在滚动 ListView 时地图滚动出视图,但我也希望用户能够与地图进行交互。所以滚动应该只在用户在其他 ListView 小部件上滚动时发生,而不是在他们在地图上滚动时发生,然后我希望手势直接应用于地图。目前,当用户在地图上滚动时,它会滚动整个 ListView。

我已经尝试了我在这里遇到的另一个建议 在 Flutter 中,子小部件如何防止其可滚动父部件的滚动?GestureDetector在上面的帖子的答案中添加了一个将地图容器包装在下面的示例中的建议,但是这只是在地图上滚动时阻止了 ListView 和 Map 的滚动。视频链接https://imgur.com/SeCRzUC

这是我的构建方法返回的小部件。此代码取决于google_maps_flutter插件。

Container(
  height: MediaQuery.of(context).size.height,
  child:
  ListView.builder(
    itemCount: 12 + 1,
    itemBuilder: (context, index) {
      if (index == 0) return GestureDetector(
        onVerticalDragUpdate: (_){},
        child: Container(
          height: MediaQuery.of(context).size.height / 2,
          child: GoogleMap(initialCameraPosition: initalPosition),
        ),
      );
      else return ListTile(title: Text("$index"),);
    }
  )
),
Run Code Online (Sandbox Code Playgroud)

我曾希望地图会捕获手势,但它没有,包含它的列表视图会捕获所有手势。谁能建议我如何强制将列表中此项目的所有手势直接传递给地图,并且在滚动列表中的其他项目时仍然使列表滚动?

cam*_*ski 19

接受的答案很复杂,在我的情况下它甚至不起作用!它提供了从左到右的滚动、平移和缩放,但是从上到下的滚动仍然会滚动ListView.

真正的解决方案非常简单,因为GoogleMap默认情况下有这些手势检测器。您必须仅指定手势检测必须由GoogleMap和不是优先ListView。例如,这是通过以下列方式给出GoogleMap对象 a来实现的EagerGestureRecognizer

ListView(
  children: <Widget>[
    Text('a'),
    Text('b'),
    GoogleMap(
      ...,
      gestureRecognizers: {
        Factory<OneSequenceGestureRecognizer>(
          () => EagerGestureRecognizer(),
        ),
      },
    ),
  ],
)
Run Code Online (Sandbox Code Playgroud)

通过这种方式,发生在GoogleMap对象上或上方的所有手势都将被优先考虑GoogleMap而不是任何其他小部件。


Ese*_*met 9

编辑:campovski在下面的回答是更新后的答案。

Depreciated Answer:

  • 如果您想在滚动时从屏幕上移出 GoogleMap 小部件,请使用 ListView 包装所有内容。

  • 使用 GoogleMap 手势识别器覆盖 ListView 滚动物理。

  • 由于 ListView 物理之间的冲突,禁用 ListView.builder 滚动物理。

首先导入依赖项:

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
Run Code Online (Sandbox Code Playgroud)

构建方法:

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: <Widget>[
          SizedBox(
            height: MediaQuery.of(context).size.height / 2,
            child: GoogleMap(
              initialCameraPosition:
                  CameraPosition(target: LatLng(41, 29), zoom: 10),
              gestureRecognizers: Set()
                ..add(
                    Factory<PanGestureRecognizer>(() => PanGestureRecognizer()))
                ..add(
                  Factory<VerticalDragGestureRecognizer>(
                      () => VerticalDragGestureRecognizer()),
                )
                ..add(
                  Factory<HorizontalDragGestureRecognizer>(
                      () => HorizontalDragGestureRecognizer()),
                )
                ..add(
                  Factory<ScaleGestureRecognizer>(
                      () => ScaleGestureRecognizer()),
                ),
            ),
          ),
          ListView.builder(
            physics: const NeverScrollableScrollPhysics(),
            shrinkWrap: true,
            itemCount: 12,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text("$index"),
              );
            },
          )
        ],
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)