从视图的长按触发DOWN事件时,从对话框中注册UP/CANCEL。

7
我有一个UX需求,用户通过长按GridView中的单元格来触发Dialog
  • Dialog显示时,用户必须能够在屏幕上移动手指/拇指而不触发GridView单元格边界之外的UP/CANCEL事件。

  • 当用户最终与屏幕断开联系时,我想捕捉这个事件。相比其他视图,GridView似乎会注册一些UP/CANCEL的误报。

  • 问题在于原始视图捕捉到了所有触摸事件,因为DOWN被它捕获了。

  • 对话框仅在原始视图的UP事件后注册/接收到触摸事件。

我尝试取消原始触摸事件并使用dispatchTouch()等方法,但都没有成功。

你有什么好的点子吗?


请更具体一点,我不明白你想做什么。 - MineConsulting SRL
当在活动或片段中的视图被长按时,触发对话框的显示(已经实现)。用户必须能够将手指移开触发对话框的视图,但不能与屏幕断开联系。仅当用户断开与屏幕的联系时,才会触发另一个事件。问题:当移动到原始视图范围之外时,会触发ACTION_UP和/或ACTION_CANCEL,并且对话框(或其他任何内容)不会注册任何触摸,直到用户断开与屏幕的联系并重新触摸。 - Bill Mote
我已经做过类似的事情,但没有使用网格视图。用户必须长按,然后会出现一个对话框,用户可以在按住的同时随意移动手指,当用户放开手指时,对话框会隐藏。请考虑制作一个视频并在这里发布。我不理解这部分内容(在用户与屏幕断开联系并重新触摸之前,对话框(或任何其他东西)都不会注册任何触摸)。 - AZ_
由于应用程序正在开发中,我无法向您提供演示 :/ - AZ_
1
如果您的问题是前一个视图捕获了所有未来的触摸事件,那么这是因为它维护了一个触摸事件列表。我建议您查看源代码。 - AZ_
我需要准备一个示例,因为我不能公开使用这个项目的代码。 - Bill Mote
1个回答

2

我在我的一个项目中使用了类似的东西。

OnTouchListener分配给你的gridView中的每个单元格,并重写OnTouch方法。

@Override
public boolean onTouch(View v, MotionEvent event) {

boolean isLongPressed;

int mSwipeSlop = ViewConfiguration.get(context).
                getScaledTouchSlop();

boolean mSwiping;

switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        handler.postDelayed(mLongPressed, 1000);
        break;

    case MotionEvent.ACTION_CANCEL:
        handler.removeCallbacks(mLongPressed);
        break;

    case MotionEvent.ACTION_MOVE:
        float x = event.getX() + v.getTranslationX();
            float deltaX = x - mDownX;
            float deltaXAbs = Math.abs(deltaX);
            float y = event.getY() + v.getTranslationY();
            float deltaY = Y - mDownY;
            float deltaYAbs = Math.abs(deltaY);
            float absDist = Math.sqrt(Math.pow(deltaXAbs, 2) + Math.pow(deltaXAbs, 2));
            if (!mSwiping) {
                if (absDist > mSwipeSlop) {
                    mSwiping = true;
                    handler.removeCallbacks(mLongPressed);
                }
            }
        break;

    case MotionEvent.ACTION_UP:
        handler.removeCallbacks(mLongPressed);
        if (isLongPressed) {
             // DO ACTION UP
        }
        break;

    default: 
        return false;
    }
return true;
}

在可运行的mLongPressed中打开对话框,只有当用户连续触摸同一位置一秒钟时才会运行。您当然可以更改他可以移动的距离和需要按下以注册为长按的时间。然而,我建议使用getScaledTouchSlop()来获取距离。

final Handler handler = new Handler(); 
Runnable mLongPressed = new Runnable() { 
    public void run() { 
        // OPEN DIALOG
        isLongPressed = true;
    }   
};

通过在我的项目中使用这段代码,用户可以在整个屏幕上移动手指而不会触发ACTION_UP。只有当他抬起手指时才会触发。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接