繁体   English   中英

如何为 ImageButton 组合 OnClickListener 和 OnTouchListener

[英]How to combine OnClickListener and OnTouchListener for an ImageButton

当用户单击ImageButton时我需要做一些事情 我试图创建一个同时实现OnClickListenerOnTouchListener的静态类

static class ClickListenerForScrolling implements OnClickListener, OnTouchListener 

具有以下方法:

@Override
public void onClick(View v)

@Override
public boolean onTouch(View arg0, MotionEvent arg1)

这背后的整个想法是在用户触摸时更改ImageButton的图像源,并在用户单击此按钮时执行任务。 任何人都可以提示我如何执行此操作吗?

由于这两个动作都包括“将手指放在屏幕上 - 手指从屏幕上抬起”的手势,因此无法确定是触摸动作还是点击动作。 因此,如果您在此图像按钮上实现两个侦听器,则触摸/单击将更改图片并按下按钮。 不确定这些事件是否有确定的顺序......

但是,如果要分离这些事件,则需要为其中一个操作定义不同的手势(例如擦除以更改图片),或创建处理事件的不同区域,例如图像不适合整个按钮和空闲区域用作按钮点击区域。

HTH

更新:

我发现, TouchEventClickEvent更通用,因此首先调用它。

public abstract boolean onTouch (View v, MotionEvent event)

如果侦听器已使用该事件,则返回true,否则返回false。 因此,您可以在实现中决定是否也应该由OnClickListener处理事件,然后返回false

onTouchListener能够处理这两种动作。

event.action()值之间Switch以获取MotionEvent

case MotionEvent.ACTION_DOWN :是第一次手指撞击。
case MotionEvent.ACTION_UP :是手指消失的时候。

您必须在ACTION_DOWN上设置影响点。

TheImpactPoint=event.getX();

然后用ACTION_UP获取距离

float distance =TheImpactPoint-event.getX();

If distance = 0则存在咔嗒声,否则根据手势它将大于或小于零。

因此,这是在没有实际点击事件的情况下使用click事件并仅使用onTouchListener

希望会有用。

使用此代码:

public class GestureHelper implements OnTouchListener {

private final GestureDetector mGestureDetector;

public GestureHelper(Context context) {
    mGestureDetector = new GestureDetector(context, new GestureListener(this));
}

public void onSwipeRight() {
};

public void onSwipeLeft() {
};

public void onSwipeTop() {
};

public void onSwipeBottom() {
};

public void onDoubleTap() {
};

public void onClick() {
};

@Override
public boolean onTouch(View v, MotionEvent event) {
    return mGestureDetector.onTouchEvent(event);
}

private static final class GestureListener extends SimpleOnGestureListener {

    private static final int SWIPE_THRESHOLD = 100;
    private static final int SWIPE_VELOCITY_THRESHOLD = 100;
    private GestureHelper mHelper;

    public GestureListener(GestureHelper helper) {
        mHelper = helper;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        mHelper.onClick();
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        mHelper.onDoubleTap();
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        boolean result = false;
        try {
            float diffY = e2.getY() - e1.getY();
            float diffX = e2.getX() - e1.getX();
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        mHelper.onSwipeRight();
                    } else {
                        mHelper.onSwipeLeft();
                    }
                }
            } else {
                if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        mHelper.onSwipeBottom();
                    } else {
                        mHelper.onSwipeTop();
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }
}

}

扩展这个类并像这样使用...

view.setOnTouchListener(new SomeYourGestureHelper(context, someParameters));

使用return false而不是return true

这个问题有很多解决方案,对我来说最好的方法是完全消除setOnClickListener,并在onTouchListener内部检查操作是否为ACTION_UP,然后在内部检查前一个是否为ACTION_DOWN:

case MotionEvent.ACTION_UP:
    if (lastAction == MotionEvent.ACTION_DOWN) {
        //code for click   
        .
        .
        lastAction = event.getAction();
    }

lastAction是int,我在每个ACTION结束时更新它

您可以结合使用GestureDetectorsetOnTouchListener来实现这一点,而不是基于距离/时间差异的方法。 GestureDetector会检测点击,而您可以将OnTouchListener用于其他基于触摸的事件,例如检测拖动。

下面是一个示例代码供参考:

Class MyCustomView() {

    fun addClickAndTouchListener() {
        val gestureDetector = GestureDetector(
            context,
            object : GestureDetector.SimpleOnGestureListener() {
                override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
                    // Add your onclick logic here
                    return true
                }
            }
        )

        setOnTouchListener { view, event ->
            when {
                gestureDetector.onTouchEvent(event) -> {
                    // Your onclick logic would be triggered through SimpleOnGestureListener
                    return@setOnTouchListener true
                }
                event.action == MotionEvent.ACTION_DOWN -> {
                    // Handle touch event
                    return@setOnTouchListener true
                }
                event.action == MotionEvent.ACTION_MOVE -> {
                    // Handle drag
                    return@setOnTouchListener true
                }
                event.action == MotionEvent.ACTION_UP -> {
                    // Handle Drag over
                    return@setOnTouchListener true
                }
                else -> return@setOnTouchListener false
            }
        }

    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM