如何处理Google地图API v2中地图的onTouch事件?

33

谷歌地图默认不提供地图拖动开始和结束事件。 我已经在这里报告了这个问题

我想制作一个自定义处理程序,它将使用普通的 onTouch 事件,并将其与 setOnCameraChangeListener 结合使用。

但是我找不到如何访问 GoogleMap 对象的 onTouch 事件。 它没有提供这样的回调

我想知道如何在Google Map API v2中处理地图的触摸事件?


叠加层怎么样?它们在API v2中仍然有onTouchEvent()回调吗? - Andrii Chernenko
现在不再有覆盖层。对于标记和几何对象,它们引入了单独的方法。 - Alexey Zakharov
为什么不使用CameraChangeListener呢? - Melbourne Lopes
2个回答

41

以下是用于确定拖拽开始和拖拽结束事件的一种可能解决方法:

您需要扩展SupportMapFragmentMapFragment。在onCreateView()中,您需要将您的MapView放到自定义的FrameLayout(在下面的示例中,它是TouchableWrapper类)中,在其中截取触摸事件并识别地图是否被点击。如果调用了您的onCameraChange,只需检查地图视图是否被按下或未被按下(在下面的示例中,这是变量mMapIsTouched)。

示例代码:

更新1:

  • getView()中返回原始创建的视图
  • 使用dispatchTouchEvent()代替onInterceptTouchEvent()

自定义的FrameLayout:

private class TouchableWrapper extends FrameLayout {
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
        mMapIsTouched = true;
        break;

    case MotionEvent.ACTION_UP:
        mMapIsTouched = false;
        break;
        }

        return super.dispatchTouchEvent(ev);
    }
    }

在您的自定义MapFragment中:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
    mOriginalContentView = super.onCreateView(inflater, parent, savedInstanceState);

    mTouchView = new TouchableWrapper(getActivity());
    mTouchView.addView(mOriginalContentView);

    return mTouchView;
}

@Override
public View getView() {
    return mOriginalContentView;
}

在您的相机更改回调方法中:

private final OnCameraChangeListener mOnCameraChangeListener = new OnCameraChangeListener() {
    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        if (!mMapIsTouched) {
            refreshClustering(false);
        }
    }
};

@Alexey Zakharov,我尝试了一下,但是出现了错误:第一个错误出现在getActivity上。你能否发布你自定义的MapFragment类声明?(或者整个代码) - Gaucho
你需要扩展SupportMapFragment或MapFragment。 - AZ13
1
@AZ13,我使用了你的解决方案作为基础,但是我通过使用自定义监听器而不是公共静态变量来改进它。请参见我的解决方案如下。此外,在您的情况下,在OnCameraChangeListener中使用mMapIsTouched布尔值大多数情况下不起作用,因为OnCameraChangeListener更常见地在布尔值更新之前触发,因此if中的代码永远不会触发。 - Dimitar Darazhanski
1
@AZ13,非常棒的回答。如果你或其他人感兴趣,我刚刚创建了一个库,用于管理可拖动的覆盖框,以此回答为灵感。在这里找到它:https://github.com/mattlogan/DraggableOverlayBox - Matt Logan
显示剩余2条评论

7

有一种更简单的方法来处理这个问题,可以在onCameraMoveStarted监听器上处理您的情况,就像这样:

下面是代码片段:

@Override
public void onCameraMoveStarted(int reason) {
    if (reason == OnCameraMoveStartedListener.REASON_GESTURE) {
        Toast.makeText(this, "The user gestured on the map.",
                       Toast.LENGTH_SHORT).show();
    } else if (reason == OnCameraMoveStartedListener
                            .REASON_API_ANIMATION) {
        Toast.makeText(this, "The user tapped something on the map.",
                       Toast.LENGTH_SHORT).show();
    } else if (reason == OnCameraMoveStartedListener
                            .REASON_DEVELOPER_ANIMATION) {
        Toast.makeText(this, "The app moved the camera.",
                       Toast.LENGTH_SHORT).show();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接