开发者

How can you detect which view you are passing over when performing a touch event?

开发者 https://www.devze.com 2023-01-28 06:15 出处:网络
I want to know how I can detect child views if I move a view from one ViewGroup to another ViewGroup, particularly when doing a touch event. Is there a method I can call that will let me know which vi

I want to know how I can detect child views if I move a view from one ViewGroup to another ViewGroup, particularly when doing a touch event. Is there a method I can call that will let me know which views i'm "hovering" over?

What I'm doing right now is when I开发者_开发百科 detect an ACTION_MOVE event on my view i'm raising it to the top level parent so that it can move and be drawn within the entire window ( and not just inside it's original parent bounds ), then I want to move the view across to a different ViewGroup and on ACTION_UP attach the view to that ViewGroup.


Inspired by Ami's response, but discovering that MotionEvent#getX()/getY() along with View#getTop()/etc return coordinates wrt the parent View, I ended up doing the following below to operate in screen coordinates, allowing me to work across ViewGroups:

        private boolean inRegion(float x, float y, View v) {
            v.getLocationOnScreen(mCoordBuffer);
            return mCoordBuffer[0] + v.getWidth() > x &&    // right edge
                   mCoordBuffer[1] + v.getHeight() > y &&   // bottom edge
                   mCoordBuffer[0] < x &&                   // left edge
                   mCoordBuffer[1] < y;                     // top edge
        }

whose usage inside an OnTouchListener is e.g.:

        boolean inside = inRegion(event.getRawX(), event.getRawY(), targetView);


I think I found a simpler way to do this.

  1. Create an ArrayList of possible targets
  2. Call this method from your touch event, supplying your targets list and the coords
private View findView(float x, float y, ArrayList<View> targets)
{
    final int count = targets.size();
    for (int i = 0; i < count; i++) {
        final View target = targets.get(i);
        if (target.getRight() > x && target.getTop() < y
                && target.getBottom() > y && target.getLeft() < x) {
            return target;
        }
    }
    return null;
}


I found Sebastian Roth's answer very helpful with resources, but since it wasn't really an answer to my question, I thought I'd share what I came up with.

Here is the code I use to detect views ( only views that will accept a drop that is ) given a coordinate on the screen.

            private DropView findDropTarget( int x, int y, int[] dropCoordinates ){
                final Rect r = mRectTemp;
                final ArrayList<DropView> dropTargets = ((main) context).getBoardDropTargets();
                final int count = dropTargets.size();
                for (int i=count-1; i>=0; i--) {
                    final DropView target = dropTargets.get(i);
                    target.getHitRect(r);
                    target.getLocationOnScreen(dropCoordinates);
                    r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop());
                    if (r.contains(x, y)) {
                        dropCoordinates[0] = x - dropCoordinates[0];
                        dropCoordinates[1] = y - dropCoordinates[1];
                        return target;
                    }
                }
           }

Ok, first off mRectTemp is just an allocated Rectangle so you don't have to keep creating new ones ( I.E. final Rect r = new Rect() )

The next line dropTargets is a list of views that will accept a drop in my app. Next I loop through each view.

I then use getHitRect(r) to return the screen coordiantes of the view.

I then offset the coordiantes to account for the notification bar or any other view that could displace the coordiantes.

finally I see if x and y are inside the coordinates of the given rectangle r ( x and y are the event.rawX() and event.rawY() ).

It actually turned out to be simpler then expected and works very well.


Read this:
http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent)
http://developer.android.com/reference/android/view/View.html#onTouchEvent(android.view.MotionEvent)
I had implemented a Drag and Drop using that method.

I also highly recommend a read of the HomeScreen sourcecode, which contains this thing (kind of):
https://android.googlesource.com/platform/packages/apps/Launcher2

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号