检测触摸按、长按与移动?

2022-08-31 14:29:54

我目前正在摆弄Android编程,但我在检测不同的触摸事件时遇到了一个小问题,即正常的触摸按(在屏幕上按并立即释放),长按(触摸屏幕并按住手指)和移动(在屏幕上拖动)。

我想做的是在我的屏幕上有一个图像(一个圆圈),我可以拖来拖去。然后,当我按下它一次(短/正常按)时,Toast会提出一些关于它的基本信息。当我长按它时,会出现一个带有列表的AlertDialog,以选择不同的图像(圆形,矩形或三角形)。

我用自己的OnTouchListener制作了一个自定义视图来检测事件并在onDraw中绘制图像。OnTouchListener.onTouch是这样的:

// has a touch press started?
private boolean touchStarted = false;
// co-ordinates of image
private int x, y;

public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    if (action == MotionEvent.ACTION_DOWN) {
        touchStarted = true;
    }
    else if (action == MotionEvent.ACTION_MOVE) {
        // movement: cancel the touch press
        touchStarted = false;

        x = event.getX();
        y = event.getY();

        invalidate(); // request draw
    }
    else if (action == MotionEvent.ACTION_UP) {
        if (touchStarted) {
            // touch press complete, show toast
            Toast.makeText(v.getContext(), "Coords: " + x + ", " + y, 1000).show();
        }
    }

    return true;
}

问题在于,按压机不能像预期的那样工作,因为当我随意触摸屏幕时,它也会检测到一点点移动,并取消触摸按并围绕图像移动。

我“黑客”围绕这一点,我引入了一个新的变量“mTouchDelay”,我在ACTION_DOWN上将其设置为0,在MOVE中增加,如果它在MOVE中> = 3,我会执行我的“移动”代码。但我有一种感觉,这并不是真正的出路。

我也没有发现如何检测长按。罪魁祸首真的是MOVE,它似乎总是触发。

有关我粗略想要的示例,请参阅Android应用程序“DailyStrip”:它显示了漫画的图像。如果它对于屏幕来说太大,您可以拖动它。您可以点击它一次以弹出某些控件,然后长按它以获取选项菜单。

PS.我正在尝试让它在Android 1.5上运行,因为我的手机只能在1.5上运行。


答案 1

此代码可以区分单击和移动(拖动、滚动)。在 onTouchEvent 中,设置一个标志 isOnClick,并且初始 X、Y 坐标位于ACTION_DOWN。清除ACTION_MOVE上的标志(注意经常检测到无意的移动,这可以通过THRESHOLD const解决)。

private float mDownX;
private float mDownY;
private final float SCROLL_THRESHOLD = 10;
private boolean isOnClick;

@Override
public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            mDownX = ev.getX();
            mDownY = ev.getY();
            isOnClick = true;
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            if (isOnClick) {
                Log.i(LOG_TAG, "onClick ");
                //TODO onClick code
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if (isOnClick && (Math.abs(mDownX - ev.getX()) > SCROLL_THRESHOLD || Math.abs(mDownY - ev.getY()) > SCROLL_THRESHOLD)) {
                Log.i(LOG_TAG, "movement detected");
                isOnClick = false;
            }
            break;
        default:
            break;
    }
    return true;
}

对于上面建议的LongPress来说,GestureDetector是要走的路。检查这个问答:

使用安卓设备检测长按


答案 2

从安卓文档 -

上长点击()

From View.OnLongClickListener.当用户触摸并按住项目(在触摸模式下)或使用导航键或轨迹球聚焦在项目上并按住合适的“Enter”键或按住轨迹球(一秒钟)时,将调用此选项。

onTouch()

From View.OnTouchListener.当用户执行限定为触摸事件的操作(包括按下、释放或屏幕上的任何移动手势)(在项目的边界内)时,将调用此选项。

至于“即使我触摸时也会移动”,我会设置一个delta,并确保在启动移动代码之前,视图至少已经移动了delta。如果不是,请启动触摸代码。


推荐