Android 如何为 ImageButton 组合 OnClickListener 和 OnTouchListener

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11578718/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:07:40  来源:igfitidea点击:

How to combine OnClickListener and OnTouchListener for an ImageButton

androidonclicklistenerontouchlistener

提问by Tobias Moe Thorstensen

I need to do something when the user clicks the ImageButtonI've tried to create a static class that implements bothOnClickListenerand OnTouchListener

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

static class ClickListenerForScrolling implements OnClickListener, OnTouchListener 

that has the following methods:

具有以下方法:

@Override
public void onClick(View v)

and

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

The whole idea behind this is to change the image source of the ImageButtonwhen the user touches it, and perform a task when the user clicks this button. Can anybody give me a hint on how to do this?

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

回答by Sven Menschner

Since both actions consist of the gestures "put finger on screen - lift finger from screen" you can't determine if it was touch action or a click action. So if you implement both listeners on this image button, a touch/click will change the picture AND press the button. Not sure if there is a determined order of these events...

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

However, if you want to separate these events, you will either need to define to a different gesture to one of the actions (like wiping to change picture), or create different areas who handle the events, for example the image doesn't fit the whole button and the free area serves as button click area.

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

HTH

HTH

Update:

更新:

I figured out, that a TouchEventis more general than a ClickEventthus it is called first.

我发现, aTouchEvent比 a 更通用,ClickEvent因此首先调用它。

public abstract boolean onTouch (View v, MotionEvent event)

This returns true, if the listener has consumed the event, false otherwise. So you can decide in your implementation if the Event should also be handled by OnClickListener, then just return false.

如果侦听器消耗了事件,则返回 true,否则返回 false。所以你可以在你的实现中决定事件是否也应该由 OnClickListener 处理,然后只返回false.

回答by SUARPI - Oscar G.

The onTouchListeneris able to handle both movements.

onTouchListener是能够同时处理的动作。

Switchbetween event.action()values to obtain MotionEvent.

Switchevent.action()值之间获得MotionEvent

case MotionEvent.ACTION_DOWN: is the first finger impact.
case MotionEvent.ACTION_UP: is when the finger goes away.

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

You'll have to set the impact point on ACTION_DOWN.

您必须将撞击点设置为ACTION_DOWN

TheImpactPoint=event.getX();

TheImpactPoint=event.getX();

And then obtain the distance with ACTION_UP

然后获得距离 ACTION_UP

float distance =TheImpactPoint-event.getX();

float distance =TheImpactPoint-event.getX();

If distance = 0then there is a click, otherwise it would be more or less than zero depending on gesture.

If distance = 0然后有一个点击,否则它会大于或小于零取决于手势。

So this is the way to use the click event without a real click event and using only the onTouchListener.

所以这是在没有真正的点击事件的情况下使用点击事件并且只使用onTouchListener.

Hope will be useful.

希望会有用。

回答by siarhei sin

Use this code:

使用此代码:

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;
    }
}

}

Extend this class and use like this...

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

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

回答by stannums

Use return falseinstead of return true

使用return false代替return true

回答by Mohammad Elsayed

There are many solutions for this problem, the best one for me is to eliminate totally the setOnClickListener and inside the onTouchListener do check if the action is ACTION_UP and then inside that check if the last before that is ACTION_DOWN:

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

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

lastAction is int and I update it at the end of each ACTION

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