AndroidStudio MotionEvent:在第二个视图中仅检测 ACTION_UP,在第一个视图中开始 ACTION_DOWN

AndroidStudio MotionEvent: detect only ACTION_UP on a second view, starting ACTION_DOWN on first view

根据emandt的建议解决了。下面添加了我的个人解决方案。

我为此使用 Android Studio。

我搜索了解决方案,但找不到类似的解决方案。

我想知道在另一个 ImageView 上启动 DOWN 动作时,哪个 ImageView 发生了 UP 动作(最终能够将一个图像拖到另一个图像上,并通过获取我拖过来的图片)。

我的示例有两个 ImageView,id 分别为 imageView(左)和 imageView2(右)。 在我的示例中,我还没有拖动任何东西,我只想触摸左图,查看日志中的 "Action was down",然后将手指移到显示 "Action was up2".

的右图上

我不知道这是否容易实现。

据我从测试中得知,MotionEvent.ACTION_UP 仅在您事先按下 ImageView 时才会触发它。因此,当我在 imageView2 之上发布时,它只显示左侧图像中的 "Action was up" 。

我想知道是否可以通过设置 return false 来实现,因为 return 值表明是否消耗了 ActionEvent,所以我想如果 imageView returns 的 UP 事件false,也许它确实触发了 imageView2 的 UP 事件但没有。 (要么是我的完全误解,要么是它无法识别第二个 UP,因为它不是以 DOWN 开头的,而 MotionEvents 可能总是必须以 DOWN 开头)。

public class MainActivity extends Activity {
ImageView imageView;
ImageView imageView2;
String DEBUG_TAG = "action";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageView = findViewById(R.id.imageView);
    imageView2 = findViewById(R.id.imageView2);

    imageView.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            //int action = MotionEventCompat.getActionMasked(event);
            int action = event.getActionMasked();

            switch(action) {
                case (MotionEvent.ACTION_DOWN) :
                    Log.d(DEBUG_TAG,"Action was DOWN"+v.toString());
                    return true;
                case (MotionEvent.ACTION_MOVE) :
                    //Log.d(DEBUG_TAG,"Action was MOVE");
                    return true;
                case (MotionEvent.ACTION_UP) :
                    Log.d(DEBUG_TAG,"Action was UP"+v.toString());
                    return false;

                default :
                    //return true;
            }
            return true;
        }
    });

    imageView2.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
            //int action = MotionEventCompat.getActionMasked(event);
            int action = event.getActionMasked();

            switch(action) {
                case (MotionEvent.ACTION_DOWN) :
                    Log.d(DEBUG_TAG,"Action was DOWN2"+v.toString());
                    return true;
                case (MotionEvent.ACTION_MOVE) :
                    //Log.d(DEBUG_TAG,"Action was MOVE");
                    return true;
                case (MotionEvent.ACTION_UP) :
                    Log.d(DEBUG_TAG,"Action was UP2"+v.toString());
                    return true;

                default :
                    //return true;
            }
            return true;
        }
    });
}

}

如果没有简单的方法来做到这一点,我正在考虑用数学方法解决这个问题,但也许你们中的一些人可以提供帮助。

所以我的问题是,有没有办法在当前处于另一个 ImageView 的 MotionEvent 中时识别第二个 ImageView 上的 UP 操作?

解决方案(参见 emandt 的回答)

我放弃了第二个 OnClickListener,因为我意识到第二个图像不需要任何,我只需要它的位置。

添加了这个方法:

 @Nullable
private View getDroppedView(View droppedView, int x, int y, List<View> arrayOfPossibilities) {
    Rect cVisibleBoundsRect = new Rect();
    for (View cView : arrayOfPossibilities) {
        //if currently iterated view doesn't have values for getGlobalVisibleRect, skip the .contains part
        //ignore the item which is your current active item (which would potentially be dropped)
        //getGlobalVisibleRect sets cVisibleBoundsRect immediately to the Rect given as parameter
        if (!cView.getGlobalVisibleRect(cVisibleBoundsRect)||(cView.equals(droppedView))) continue;
        if (cVisibleBoundsRect.contains(x, y)) {
            Log.d(DEBUG_TAG,"Found something");
            //THIS "cView" IS THE VIEW WHERE YOU RELEASED THE FINGER
            return cView;
        }
    }
    Log.d(DEBUG_TAG,"Found nothing");
    return null;
}

并在 onUP 中添加:

case (MotionEvent.ACTION_UP) :
                    View dropTarget;
                    Log.d(DEBUG_TAG,"Action was UP"+v.toString());
                    dropTarget = getDroppedView(v, (int)event.getRawX(), (int)event.getRawY(), listOfViews);

                   if (dropTarget != null){
                        v.setX(dropTarget.getX());
                        v.setY(dropTarget.getY());
                    }

我想你想知道你从屏幕上松开手指的视图是哪个,对吗?

为此,您可以对所有视图使用相同的 "View.OnTouchListener()",并且在 ACTION_UP 中,您必须调用类似于此(伪代码)的新方法:

....
case (MotionEvent.ACTION_UP) :
    View[] cArrayOfPossibileViews = new View[]{ findViewById(IMAGE_1), findViewById(IMAGE2) }
    getDroppedView(v, event.getRawX(), event.getRawY(), cArrayOfPossibileViews);
    break;
}
....

@Nullable
private View getDroppedView(View view, int x, int y, View[] arrayOfPossibilities) {
    Rect cVisibleBoundsRect = new Rect();
    for (View cView : arrayOfPossibilities) {
        if (!cView.getGlobalVisibleRect(cVisibleBoundsRect)) continue;
        if (cVisibleBoundsRect.contains(x, y)) {
            //THIS "cView" IS THE VIEW WHERE YOU RELEASED THE FINGER
            return cView;
        }
    }
    return null;
}

此方法获取视图边界并将它们与触摸事件的 X 和 Y 进行比较。如果 X 和 Y 包含在 View 边界内,则表示该 View 是您需要的。