【问题标题】:Overriding onTouchEvent competing with ScrollView覆盖与 ScrollView 竞争的 onTouchEvent
【发布时间】:2011-09-05 21:19:37
【问题描述】:

从一个简单的概述中,我有一个自定义视图,其中包含一些用户可以拖动和调整大小的位图。

我这样做的方式是相当标准的,因为我在 CustomView 中覆盖 onTouchEvent 并检查用户是否在图像中触摸等。

当我想将此 CustomView 放在 ScrollView 中时,我的问题就出现了。这可行,但 ScrollView 和 CustomView 似乎在争夺 MotionEvents,即当我尝试拖动图像时,它要么移动缓慢,要么视图滚动。

我在想我可能必须扩展一个 ScrollView 以便我可以覆盖 onInterceptTouchEvent 并让它知道用户是否在图像的范围内不要尝试滚动。但是由于 ScrollView 在层次结构中较高,我将如何访问 CustomView 的当前状态?

有没有更好的办法?

【问题讨论】:

标签: android user-interface drag-and-drop scrollview


【解决方案1】:

通常,在此类情况下,Android 会使用长按来开始拖动,因为它有助于消除用户打算拖动项目与滚动项目容器的歧义。但是,如果您在用户开始拖动项目时有明确的信号,请在您知道用户开始拖动时从自定义视图中尝试getParent().requestDisallowInterceptTouchEvent(true)。 (此方法的文档here。)这将阻止 ScrollView 拦截触摸事件,直到当前手势结束。

【讨论】:

  • 非常感谢,成功了! SO上有一些很棒的api知识:)
  • 当您让维护平台本身的这些东西的人回答您的问题时,它会有所帮助。 ;)
  • @brk3 你的解决方案是什么?我也有同样的问题,能不能给个源代码?我用的是长按,但是不好用
  • 解决了我的问题,谢谢。
  • 哇,谢谢。如果没有找到这个,我早就发现了这个
【解决方案2】:

没有一个解决方案对我来说是“开箱即用”的,可能是因为我的自定义视图扩展了 View,而不是 ViewGroup,因此我无法实现onInterceptTouchEvent.

同时调用 getParent().requestDisallowInterceptTouchEvent(true) 是在抛出 NPE,或者什么都不做。

最后这就是我解决问题的方法:
在您的自定义 onTouchEvent 调用 requestDisallow... 时,您的视图将处理该事件。例如:

@Override
public boolean onTouchEvent(MotionEvent event) {
    Point pt = new Point( (int)event.getX(), (int)event.getY() );
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        if (/*this is an interesting event my View will handle*/) {
            // here is the fix! now without NPE
            if (getParent() != null) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }

            clicked_on_image = true;
        }
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
        if (clicked_on_image) {
            //do stuff, drag the image or whatever
        }
    } else if (event.getAction() == MotionEvent.ACTION_UP) {
        clicked_on_image = false;
    }
    return true;
}

现在我的自定义视图工作正常,处理一些事件并让 scrollView 捕获我们不关心的事件。在这里找到解决方案:http://android-devblog.blogspot.com.es/2011/01/scrolling-inside-scrollview.html

希望对你有帮助。

【讨论】:

  • 很棒的答案,有帮助! :) 但我建议将 NullPointer 检查更改为: ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); }
【解决方案3】:

有一个名为 MotionEvent.ACTION_CANCEL(值 = 3)的 Android 事件。我所做的只是覆盖我的自定义控件的 onTouchEvent 方法并捕获此值。如果我检测到这种情况,我会做出相应的反应。

这里有一些代码:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(isTouchable) {
        int maskedAction = event.getActionMasked();         
        if (maskedAction == MotionEvent.ACTION_DOWN) {
            this.setTextColor(resources.getColor(R.color.octane_orange));
            initialClick = event.getX();
        } else if (maskedAction == MotionEvent.ACTION_UP) {
            this.setTextColor(defaultTextColor);
            endingClick = event.getX();
            checkIfSwipeOrClick(initialClick, endingClick, range);
        } else if(maskedAction == MotionEvent.ACTION_CANCEL)
            this.setTextColor(defaultTextColor);
    }
    return true;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-29
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多