重写与ScrollView竞争的onTouchEvent

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

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

当我想把这个CustomView放在一个ScrollView中时,我的问题就出现了。 这工作,但滚动视图和CustomView似乎竞争MotionEvents,即当我试图拖动图像,要么移动缓慢或视图滚动。

我想我可能不得不扩展一个滚动视图,所以我可以重写onInterceptTouchEvent并让其知道用户是否在图像的范围内,不要尝试和滚动。 但是,因为ScrollView在层次结构中更高,我将如何访问CustomView的当前状态?

有没有更好的办法?

Solutions Collecting From Web of "重写与ScrollView竞争的onTouchEvent"

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

没有发现解决scheme“开箱即用”,可能是因为我的自定义视图扩展了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抓住我们不关心的。 在这里find解决scheme: http : //android-devblog.blogspot.com.es/2011/01/scrolling-inside-scrollview.html

希望能帮助到你。

有一个名为MotionEvent.ACTION_CANCEL(value = 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; }