GestureDetector - 检测GridView项目中的双击,虽然在onTouchEvent()中返回false [英] GestureDetector - Detect double click in GridView item's although returning false in onTouchEvent()
问题描述
我写了一个简单的 ImageView
子类,用于检测 GridView
-items上的双击:
public class DoubleClickImageView扩展ImageView {
public interface ClickListener {
void onSingleClick() ;
void onDoubleClick();
}
private ClickListener imageClickReceiver;
private GestureDetector gestureDetector;
@Override
public boolean onTouchEvent(MotionEvent event){
gestureDetector.onTouchEvent(event);
// return super.onTouchEvent(event);无法使用gestureDetector
//返回false;无法使用gestureDetector
返回true; //工作但打破应用程序的其余部分
}
public void setDoubleClickListener(ClickListener listener){
imageClickReceiver = listener;
}
public DoubleClickImageView(Context cx,AttributeSet attrs){
super(cx,attrs);
gestureDetector = new GestureDetector(cx,new InternalClickListener());
private class InternalClickListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent event){
if(imageClickReceiver != null){
imageClickReceiver.onSingleClick();
}
返回true;
$ b @Override
public boolean onDoubleTap(MotionEvent e){
if(imageClickReceiver!= null){
imageClickReceiver.onDoubleClick();
}
返回true;
}
@Override
public boolean onDown(MotionEvent event){
//根据文档要求返回true on onDown,但不会帮助
返回true;
}
}
}
GridView
由使用此类显示的图像组成。
问题在于双击检测仅在 onTouchEvent
返回 true
时有效,否则中返回
,它打破了我的应用程序的其余部分,因为我还有一个全局 true
时,没有检测到任何点击事件。 > onTouchEvent onTouchListener
来检测整个 GridView
和一个长按选择模式。
我该如何解决这个问题,以使所有这三个功能一起工作? / p>
更新:我能够使用调试日志追查问题。事实证明,当最初的onTouchEvent调用( MotionEvent.ACTION_DOWN
)返回false时,相关的后续事件不会传递给 ImageView
。因此,GestureDetector无法理解它,因为它需要给定手势的所有相关MotionEvent。
我仍然需要解决此问题的解决方法。仅仅因为我需要在 ImageView
-subclass中使用 GestureDetector
而打破了整个长按上下文操作栏,
$ b $ / **
*解决方法:获取传递给GridView图像的手势的所有触摸事件,
*尽管onTouchEvent回调必须返回false以防止破坏
* GridView功能的其余部分。 (这些是滑动手势和我们的情况下的上下文操作栏)
*请参阅http://stackoverflow.com/questions/39107566/detect-double-click-on-imageview-works-only-when-ontouchevent-返回真#
* http://stackoverflow.com/questions/39100565/gesturedetector-detect-doubleclick-on-gridview-items
*了解更多信息
* /
公共类DoubleClickImageView扩展ImageView {
私人TouchEventForwarder touchEventForwarder;
private ClickListener imageClickListener;
private GestureDetector gestureDetector;
$ b $ **
*这需要在父级GridView适配器的getView()方法中调用
** /
public void setListeners(ClickListener dest,TouchEventForwarder src ){
imageClickListener = dest;
touchEventForwarder = src;
$ b $ **
*父级GridView适配器必须维护这个类的一个实例
** /
public static class TouchEventForwarder {
私人DoubleClickImageView currentClickedImage;
$ b $ **
*需要在父GridView接收的每个触摸事件上调用
** /
public void forwardTouchEvent(MotionEvent event){
if(currentlyClickedImage!= null){
currentClickedImage.onForwardedTouchEvent(event);
}
}
private void setNewReceiver(DoubleClickImageView doubleClickImageView){
currentClickedImage = doubleClickImageView;
}
}
public interface ClickListener {
void onSingleClick();
void onDoubleClick();
}
private void onForwardedTouchEvent(MotionEvent event){
/ **仅使用转发事件进行手势检测
*以防止评估重复事件** /
gestureDetector.onTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event){
/ **使用系统侦听器在事件转发器中注册视图** /
if(touchEventForwarder!= null){
touchEventForwarder.setNewReceiver(this);
}
返回super.onTouchEvent(event); //总是false
}
public DoubleClickImageView(Context cx,AttributeSet attrs){
super(cx,attrs);
gestureDetector = new GestureDetector(cx,new InternalClickListener());
$ b $ private class InternalClickListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent event){
if(imageClickListener!= null) {
imageClickListener.onSingleClick();
}
返回true;
}
@Override
public boolean onDoubleTap(MotionEvent event){
if(imageClickListener!= null){
imageClickListener.onDoubleClick();
}
返回true;
}
}
}
I wrote a simple subclass of ImageView
that I want to use to detect double clicks on GridView
-items:
public class DoubleClickImageView extends ImageView {
public interface ClickListener {
void onSingleClick();
void onDoubleClick();
}
private ClickListener imageClickReceiver;
private GestureDetector gestureDetector;
@Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
// return super.onTouchEvent(event); does not work with gestureDetector
// return false; does not work with gestureDetector
return true; // works but breaks the rest of the application
}
public void setDoubleClickListener(ClickListener listener) {
imageClickReceiver = listener;
}
public DoubleClickImageView(Context cx, AttributeSet attrs) {
super(cx, attrs);
gestureDetector = new GestureDetector(cx, new InternalClickListener());
}
private class InternalClickListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
if (imageClickReceiver != null) {
imageClickReceiver.onSingleClick();
}
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
if (imageClickReceiver != null) {
imageClickReceiver.onDoubleClick();
}
return true;
}
@Override
public boolean onDown(MotionEvent event) {
//return true for onDown is required according to docs but does not help
return true;
}
}
}
The GridView
consists of Images that are displayed using this class.
The problem is that the double click detection works only when onTouchEvent
returns true
, otherwise the gestureDetector
does not detect any click event.
However, when I return true
in the onTouchEvent
, it breaks the rest of my application, since I have also a global onTouchListener
to detect swipes over the whole GridView
and a multiple choice select mode with long press.
How can I solve this problem so that all of these three features work together?
Update: I was able to trace down the problem with debug logs. It turned out that when the initial onTouchEvent-call (MotionEvent.ACTION_DOWN
) returns false, the related follow-up-events are not delivered to the ImageView
. Therefore the GestureDetector can not make any sense of it, since it needs all related MotionEvents of a given gesture.
I still need a workaround for this issue. Breaking the whole long-press contextual action bar just because I need to use a GestureDetector
in an ImageView
-subclass is extremely bad.
I was finally able to find a workaround after reading the touch handling section of http://balpha.de/2013/07/android-development-what-i-wish-i-had-known-earlier/.
The workaround consists of manually passing MotionEvent's to the images of the GridView. Therefore I extended the DoubleClickImageView class and my GridView's adapter class as follows:
/**
* A workaround to get all touch events of a gesture delivered to GridView-images,
* although the onTouchEvent-callback has to return false to prevent breaking the
* rest of the GridView-functionality. (these are swipe gestures and a contextual action bar in our case)
* See http://stackoverflow.com/questions/39107566/detect-double-click-on-imageview-works-only-when-ontouchevent-returns-true#
* http://stackoverflow.com/questions/39100565/gesturedetector-detect-doubleclick-on-gridview-items
* for more information
*/
public class DoubleClickImageView extends ImageView {
private TouchEventForwarder touchEventForwarder;
private ClickListener imageClickListener;
private GestureDetector gestureDetector;
/**
* This needs to be called in the parent GridView adapter's getView() method
**/
public void setListeners(ClickListener dest, TouchEventForwarder src) {
imageClickListener = dest;
touchEventForwarder = src;
}
/**
* The parent GridView adapter has to maintain an instance of this class
**/
public static class TouchEventForwarder {
private DoubleClickImageView currentlyClickedImage;
/**
* This needs to be called on each touch event received by the parent GridView
**/
public void forwardTouchEvent(MotionEvent event) {
if (currentlyClickedImage != null) {
currentlyClickedImage.onForwardedTouchEvent(event);
}
}
private void setNewReceiver(DoubleClickImageView doubleClickImageView) {
currentlyClickedImage = doubleClickImageView;
}
}
public interface ClickListener {
void onSingleClick();
void onDoubleClick();
}
private void onForwardedTouchEvent(MotionEvent event) {
/** Use only forwarded events for gesture detection
* to prevent the evaluation of duplicate events **/
gestureDetector.onTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
/** Use the system listener to register the view at the event forwarder**/
if (touchEventForwarder != null) {
touchEventForwarder.setNewReceiver(this);
}
return super.onTouchEvent(event); // always false
}
public DoubleClickImageView(Context cx, AttributeSet attrs) {
super(cx, attrs);
gestureDetector = new GestureDetector(cx, new InternalClickListener());
}
private class InternalClickListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
if (imageClickListener != null) {
imageClickListener.onSingleClick();
}
return true;
}
@Override
public boolean onDoubleTap(MotionEvent event) {
if (imageClickListener != null) {
imageClickListener.onDoubleClick();
}
return true;
}
}
}
这篇关于GestureDetector - 检测GridView项目中的双击,虽然在onTouchEvent()中返回false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!