【问题标题】:AndroidStudio MotionEvent: detect only ACTION_UP on a second view, starting ACTION_DOWN on first viewAndroidStudio MotionEvent:仅在第二个视图上检测 ACTION_UP,在第一个视图上启动 ACTION_DOWN
【发布时间】:2018-12-09 11:20:40
【问题描述】:

通过使用 emandt 的建议解决了它。下面添加了我的个人解决方案。

我正在为此使用 Android Studio。

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

我想知道在另一个 ImageView 上启动 DOWN 操作时会在哪个 ImageView 上发生 UP 操作(最终能够将一个图像拖到另一个图像上并通过获取图像的位置使其对齐到相同的位置我拖过去了)。

我的示例有两个 ID 为 imageView(左)和 imageView2(右)的 ImageView。 在我的示例中,我还没有拖动任何东西,我只想触摸左侧图像,查看日志中的“Action was down”,然后将手指放在显示“Action was up2”的右侧图像上。

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

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

我想知道是否可以通过使用 return false 进行操作,因为返回值告诉是否使用了 ActionEvent,所以我想如果 imageView 的 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());
                    }

【问题讨论】:

    标签: java android android-studio ontouchlistener motionevent


    【解决方案1】:

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

    为此,您可以对所有视图使用相同的“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 是您需要的。

    【讨论】:

    • 非常感谢您的回答。是的,这基本上就是我想要的。我想使用第二张图像的 UP 事件来获取该图像的位置(因为 imageView 是 onTouch 方法的参数)。但现在我意识到,当我从屏幕上抬起手指时,我只需要以某种方式找到手指当前所在的图像。 (不是我目前正在拖动的图像)。我想我对您的回答有了基本的了解,这似乎很有帮助,但是在周末之前我没有时间真正考虑一下。我是初学者,所以我需要更多的处理时间。
    • 我设法根据您的代码示例完成了自己的解决方案,非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多