Set custom anchor when dragging a View - android

I am using Android Drag&Drop API and am trying to set the anchor of the drag shadow to the point where the touch was made in the View. The dafault behavior is to have the anchor the middle of the View.
I did some research and it seems this can be done by overriding the onProvideShadowMetrics (Point shadowSize, Point shadowTouchPoint) method in the DragShadowBuilder class. From what I understood, if I change the x,y coordinates of shadowTouchPoint it should modify the coordinates of the drag anchor.
What I did was to extend the DragShadowBuilder class like so:
class EventDragShadowBuilder extends DragShadowBuilder {
int touchPointXCoord, touchPointYCoord;
public EventDragShadowBuilder() {
super();
}
public EventDragShadowBuilder(View view, int touchPointXCoord,
int touchPointYCoord) {
super(view);
this.touchPointXCoord = touchPointXCoord;
this.touchPointYCoord = touchPointYCoord;
}
#Override
public void onProvideShadowMetrics(Point shadowSize,
Point shadowTouchPoint) {
shadowTouchPoint.set(touchPointXCoord, touchPointYCoord);
super.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
}
}
In the Fragment where I use drag&drop I created two listeners to start a drag event for a View:
mEventLongClickListener = new OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
EventDragShadowBuilder shadowBuilder = new EventDragShadowBuilder(
view, mEventTouchXCoord, mEventTouchYCoord);
view.startDrag(null, shadowBuilder, view, 0);
return true;
}
};
// We need this listener in order to get the corect coordinates for the
// drag shadow
mEventTouchListener = new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
final int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mEventTouchXCoord = (int) event.getX();
mEventTouchYCoord = (int) event.getY();
break;
}
}
return false;
}
};
And I set the tow listeners:
itemView.setOnLongClickListener(mEventLongClickListener);
itemView.setOnTouchListener(mEventTouchListener);
Everything ok up to here. But when I test the app and start the drag process, the drag shadow is centered under the touch point. So it uses the default behavior. I tried debugging and I see that mEventTouchXCoord and mEventTouchYCoord are set correctly. The method shadowTouchPoint.set(touchPointXCoord, touchPointYCoord); gets the correct coordinates but still it centers the shadow.
I don't know what I'm doing wrong. Maybe I misunderstood the API. Any help with or hint would be much appreciated.

Ok, so like Scoup said the problem was in the onProvideShadowMetrics() method. The fact is, if I remove the super constructor, super.onProvideShadowMetrics(shadowSize, shadowTouchPoint);, it will not show the drag shadow anymore.
Taking a closer look at the API method this is what I found:
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
final View view = mView.get();
if (view != null) {
shadowSize.set(view.getWidth(), view.getHeight());
shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
} else {
Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
}
}
So indeed, it resets the shadowTouchPoint to the middle of the dragged View. But it also initializes the drag shadow to the correct dimensions. While I want the drag shadow dimensions to be set correctly I don't want to reset shadowTouchPoint.
The easiest way to acheive this is to call the super constructor before initializing the shadowTouchPoint with the custom values, like so:
#Override
public void onProvideShadowMetrics(Point shadowSize,
Point shadowTouchPoint) {
super.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
shadowTouchPoint.set(touchPointXCoord, touchPointYCoord);
}
Another solution is to deal with the drag shadow View yourself and skip the super constructor altogether. I will get back with a detailed update.

I guess the problem is this line super.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
You already changed the value of shadowTouchPoint in shadowTouchPoint.set(touchPointXCoord, touchPointYCoord); but when call the super, you are passing the shadowTouchPoint that is replaced with the "super" default method, and the default behavior is center the shadowTouchPoint.
So, just remove this line.

Related

Unobtrusive popup that won't block drag n drop in Android

I have been working on the launcher app for android similar to nova launcher. I have setup OnItemLongClickListener and OnDragListener. When i long click on an icon a popup is displayed with menu like "Remove", "Change Icon" etc. Following figure shows the progress of the app with popup open while Long click.
The problem is when the popup is opened the drag works but drop doesnot work. It seems that the i cannot log the x, y position once the popup is open. Also when the drop is performed the following message is shown in logcat.
I/ViewRootImpl: Reporting drop result: false
My code goes something like this in OnDragListener
public boolean onDrag(View v, DragEvent event) {
int dragEvent = event.getAction();
switch (dragEvent)
{
case DragEvent.ACTION_DRAG_LOCATION:
//Open popup here; note: its opened only once. popup.show();
//Log.i("Position x : ", Float.toString(event.getX())); log x or y
/*code to detect x any y change amount and close the popup
once user drags the icon little further and app knows that
user is trying to drag instead of opening the popup
and hence close the popup. popup.dismiss();
*/
// other case like ACTION_DROP etx goes after this
}
}
But it seems that after the popup is opened i cannot log x or y; also the code that determines if the action was intended for "drag" or "popup open", cannot be run.
So how do i solve this problem? I want to close the popup once the drag amount in any is sufficient to know that user wants to drag. And if not stop the drag and display the popup only.
Edit
I solved the problem with popup by using both OnTouchListner and OnDragListner. Following shows my code for OnDragListner.
//bottomAppDrawer is a GridView
bottomAppDrawer.setOnDragListener(new View.OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
int dragEvent = event.getAction();
LinearLayout draggedItem = (LinearLayout) event.getLocalState(); //dragged LinearLayout
GridView targetItem = (GridView) v; /* How do i get this drop target as LinearLayout so that i can delete or swap data */
switch (dragEvent)
{
case DragEvent.ACTION_DRAG_LOCATION:
if(reset==false) {
dragPositionStart = event.getX();
reset= true;
}
if(Math.abs(dragPositionStart - event.getX())>=20) {
Log.i("Position close : ", Float.toString(dragPositionStart));
if(isPopupOpen) {
popupMenu.dismiss();
v.startDrag(data, dragShadow, itemView, 0);
Toast.makeText(mContext, "popup closed", Toast.LENGTH_SHORT).show();
isPopupOpen = false;
}
reset = false;
}
break;
case DragEvent.ACTION_DROP:
Toast.makeText(mContext, "drop" + Integer.toString(targetItem.getChildCount()), Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
Now the problem is I am getting the drop target "Gridview" as I am dropping LinearLayout in "Gridview". Also this "LinearLayout is child of the "Gridview". And i want the drop target to be another "LinearLayout" inside the same "GridView". So that i can swap data or reorder. As in figure below.
From what I understand there are two things that you want to do. 1)Reorder the Views after drag. and 2)Change the View types after the reorder.
For problem 1 since it is a grid view it sounds like we really just want to reorder the data in the adapter, and possibly change the data to cause it to display differently. But we need to figure out the position of the original item and the target destination position.
we can extend the GridView to do that:
public class DragAndDropGridView extends GridView {
public void handleMove(int x, int y, int originalPosition) {
Rect rect = new Rect();
PushbackAdapter adapter = (PushbackAdapter) getAdapter();
for (int visiblePosition = getFirstVisiblePosition(); visiblePosition <= getLastVisiblePosition(); visiblePosition++) {
// TODO verify that there are no edge cases not covered by this
View view = getChildAt(visiblePosition);
int left = view.getLeft();
int top = view.getTop();
getChildVisibleRect(view, rect, null);
rect.offsetTo(left, top);
if (rect.contains(x, y)) {
// yay the user tried drop the view at this location
// determine if they wanted to drop it here or after this side
int centerX = rect.centerX();
if (x <= centerX) {
// we want to drop it here
adapter.move(originalPosition, visiblePosition);
adapter.notifyDataSetInvalidated();
break;
} else {
// we want to drop it behind
adapter.move(originalPosition, visiblePosition + 1);
adapter.notifyDataSetInvalidated();
break;
}
}
}
}
}
That leaves us with calling the handleMoveMethod. We do that from within the ACTION_DROP method.
case DragEvent.ACTION_DROP:
handleMove((int)event.getX(), (int)event.getY(), getPositionForView(draggedItem));
Toast.makeText(mContext, "drop" + Integer.toString(targetItem.getChildCount()), Toast.LENGTH_SHORT).show();
break;
Lastly(problem 2) it sounds like you may want to change either the content of the object at the position or the type of view it is contained in. I'd suggest using the getItemViewType and getItemViewTypeCount methods if you need to have different types of views. E.g. something along the lines of the following:
private static class PushbackAdapter extends ArrayAdapter {
ArrayList<Object> mItems;
public void move(int originalPosition, int targetPosition){
// TODO verify that this move logic is correct
Object item = mItems.remove(originalPosition);
item.useLinearLayoutType(true);
mItems.add(targetPosition, item);
}
...
#Override
public int getItemViewType(int i) {
return mItems.get(i).isLeanearLayoutType()? 1 : 0;
}
There could be bugs with this so please test thoroughly
Find position of LinerLayout(which dragging) in Gridview using targetItem.pointToPosition(..).
Swipe LinerLayout using below code:
int i =targetItem.pointToPosition((int)event.getX(), (int)event.getY());
int j = Integer.parseInt(event.getClipData().getItemAt(0).getText().toString());
Collections.swap(targetItem, i, j);//swap Linerlayout
Log.i(TAG, "Swapped " + i+ " with " + j);
Code is not tested. I hope its help you. :)

How to handle click-event in RecyclerView.ItemDecoration?

I have a RecyclerView (with LinearLayoutManager) and a custom RecyclerView.ItemDecoration for it.
Let's say, I want to have buttons in the decoration view (for some reason..).
I inflate the layout with button, it draws properly. But I can't make the button clickable. If I press on it, nothing happening(it stays the same, no pressing effect) and onClick event is not firing.
The structure of ItemDecoration layout is
<LinearLayout>
<TextView/>
<Button/>
</LinearLayout>
And I'm trying to set listener in ViewHolder of the decoration
class ItemDecorationHolder extends RecyclerView.ViewHolder {
public TextView header;
public Button button;
public HeaderHolder(View itemView) {
super(itemView);
header = (TextView)itemView.findViewById(R.id.header);
button = (Button)itemView.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//.. Show toast, etc.
}
});
}
}
And i'm drawing the decoration in onDrawOver method. (actually, I'm modifying this codebase: https://github.com/edubarr/header-decor )
Any ideas? Is it doable?
Thanks!
While the real header is scroll off the screen, the visible one is drawing on canvas directly ,not like a normal interactive widget.
You have these options
Override RecyclerView.onInterceptTouchEvent(), though with some invasiveness so I prefer the next one.
Make use of RecyclerView.addOnItemTouchListener(), remember the motion event argument has been translated into RecyclerView's coordinate system.
Use a real header view, but that will go a little far I think.
If you take option 1/2, Button.setPressed(true) and redraw the header will have a visual press effect.
In addition to what Neil said,
the answer here might help.
Passing MotionEvents from RecyclerView.OnItemTouchListener to GestureDetectorCompat
And then you just need to calculate the height of the header and see if the click falls onto that header view and handle the event yourself.
private class RecyclerViewOnGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
float touchY = e.getY();
ALLog.i(this, "Recyclerview single tap confirmed y: " + touchY);
//mGroupHeaderHeight is the height of the header which is used to determine whether the click is inside of the view, hopefully it's a fixed size it would make things easier here
if(touchY < mGroupHeaderHeight) {
int itemAdapterPosition = mRecyclerView.getLayoutManager().getPosition(mRecyclerView.findChildViewUnder(0, mGroupHeaderHeight));
//Do stuff here no you have the position of the item that's been clicked
return true;
}
return super.onSingleTapConfirmed(e);
}
#Override
public boolean onDown(MotionEvent e) {
float touchY = e.getY();
if(touchY < mGroupHeaderHeight) {
return true;
}
return super.onDown(e);
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
float touchY = e.getY();
if(touchY < mGroupHeaderHeight) {
return true;
}
return super.onSingleTapUp(e);
}
}
As Neil is pointing out, things are getting more complicated than that. However by definition you can't.
So, why not including good libraries that do that and more?
I propose my hard work for clickable sticky header in my FlexibleAdapter project, which uses a real view (not decorators) to handle click events on headers when sticky.
There's also a working demo and a Wiki page on that part (and not only).

Get touch position while dragging

I have some views which I like to drag around. The views are within
a LinearLayout, which itself is within a scrollview.
I want to get the position of the current finger (touch), to
make a smooth scroll on my scrollview, depending of the
height of the current drag.
I start my draggin after a long click with the
View build-in listener startDrag
view.startDrag(null, shadowBuilder, view, 0);
I am also able to get the relativ position of the drag
on the view that is currently hovered by
view.setOnDragListener(new OnDragListener() {
#Override
public boolean onDrag(View v, DragEvent event) {
//get event positions
}
});
But this only works for the view where the drag shadow is currently on
and DragEvent only provides relative positions, not raw positions.
What I need is the position of the finger, while the drag happens. Unfortunately all onTouchEvents get consumed while dragging.
Does anybody know how I get this to work?
Ps: One way that works (kind of) which I currently use, is to calculate the
position of the touch via the dragEvent.relativePosition in combination
with the view position. But isn't there a better way to go?
OK, since there seems not to be an easier answer, I will provide my own relativly easy solution for further readers, with no need of gesture detection.
At first you need the view that receives the drag event and at second the
drag event ifself (or at least the x and y coordinates).
With fetching of the view position and some simple addition you get the
raw touch position.
This method is tested with the show pointer position developer options
to provide the correct data.
The method for the calculation looks like this:
/**
* #param item the view that received the drag event
* #param event the event from {#link android.view.View.OnDragListener#onDrag(View, DragEvent)}
* #return the coordinates of the touch on x and y axis relative to the screen
*/
public static Point getTouchPositionFromDragEvent(View item, DragEvent event) {
Rect rItem = new Rect();
item.getGlobalVisibleRect(rItem);
return new Point(rItem.left + Math.round(event.getX()), rItem.top + Math.round(event.getY()));
}
Call this method inside of your onDragListener implementation:
#Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
//etc etc. do some stuff with the drag event
break;
case DragEvent.ACTION_DRAG_LOCATION:
Point touchPosition = getTouchPositionFromDragEvent(v, event);
//do something with the position (a scroll i.e);
break;
default:
}
return true;
}
Addtional:
If you want to determinate if the touch is inside of a specific view, you can
do something like this:
public static boolean isTouchInsideOfView(View view, Point touchPosition) {
Rect rScroll = new Rect();
view.getGlobalVisibleRect(rScroll);
return isTouchInsideOfRect(touchPosition, rScroll);
}
public static boolean isTouchInsideOfRect(Point touchPosition, Rect rScroll) {
return touchPosition.x > rScroll.left && touchPosition.x < rScroll.right //within x axis / width
&& touchPosition.y > rScroll.top && touchPosition.y < rScroll.bottom; //withing y axis / height
}
It is also possible to implement a smooth scroll on a ListView based on this solution.
So that the user can drag an item out of a list, and scroll the list via dragging the item either to the top or bottom of the list view.
Cheers.

Is it possible to pass an onTouchEvent to multiple views in Android?

I have read a few questions regarding this topic on SO but haven't really found a solid answer to it.
I have a framelayout that I stack multiple custom views on, however the onTouch event only works with the top view. (the custom views are all the same view with the same onTouch event, just multiple of them)
FrameLayout
customView[2] <--- this is the last view added and the only one that receives the event
customView[1]
customView[0]
I'm testing it on Android 2.2 and am wondering if there is any way for the other views below to know where the touch happened?
EDIT (Adding some code)
I'm adding some code to hopefully help explain where I'm running into issues. At first I just automatically had the onTouchEvent return true. This made it so that the last view (in my case customerView[2]) would be the only one generating a value.
However, once I added the method to set the onTouchEvent to return true or false, now the only view returning a generated value is customView[0].
I hope this clears up what I am asking. I'm rather new to this and I appreciate you taking the time to explain it (and of course I appreciate your patience).
Also, I realize that my TextView's don't update with the value on each touchEvent, I'm working on fixing that.
My Activity:
public class MyActivity extend Activity {
CustomView[] customView;
TextView[] textView;
int numViews 3;
//FrameLayout and Params created
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
for(int i = 0; i < numViews; i++) {
customView[i] = new CustomView(this, i);
//Allows the onTouch to be handled by all Views - View[0] is the bottom view
if(i == 0) {
customView[i].setTouchBool(true); //set view's onTouch to return true
} else {
customView[i].setTouchBool(false); //set view's onTouch to return false
}
//Set TextView to display the number generated by the CustomView
textView[i].setText(Double.toString(customView[i].getGeneratedNumber()));
//Add views to main layout
frame.addView(textView[i]);
frame.addView(customView[i]);
}
}
}
My View:
public class CustomView extends View {
boolean onTouchHandler = true;
int xVal = 0, yVal = 0;
int index;
double generatedNum = 0;
public CustomView(Context context) {
this(context, 0);
this.index = 0;
}
public CustomView(Context context, int index) {
super(context);
this.index = index;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN: {
//do logic
}
case MotionEvent.ACTION_MOVE: {
//do logic
}
case MotionEvent.ACTION_UP: {
xVal = (int) ev.getX();
yVal = (int) ev.getY();
generateNumber(xVal, yVal, index);
break;
}
}
return onTouchHandler;
}
private void generateNumber(int x, int y, int index) {
if(index == 0) {
generatedNum = (x / 2) * (y / 2) + 64;
} else {
generatedNum = (x / 2) * (y / 2) + (index * 128);
}
}
public double getGeneratedNumber() {
return generatedNum;
}
public boolean setTouchBool(boolean b) {
this.onTouchHandler = b;
}
}
Android will cascade down the views calling onTouchEvent on each one until it receives a true from one of them. If you want a touch event to be handled by all of them, then return false until it reaches the last one.
EDIT:
Ok. If I understand correctly, you have a single top view containing a bunch of child views one layer deep. My original answer was assuming that you had three custom views that were on top of each other in the ViewGroup's hierarchy (View3 is a child of View2. View2 is a child of View1. View1 is a child of ParentView). You want the user's touch event on the parent view to get sent to all of it's children.
If that's the case, AFAIK, there is no view in Android's API that allows that. So, you'll have to make a custom view that does it.
OK, I haven't tested this, so please tell me if it works and if it's what you're trying. Create a custom class that extends whatever object frame is, then override the onTouch method like so.
#Override
public boolean onTouchEvent(MotionEvent ev) {
for(int i = 0; i < this.getChildCount(); i++){
this.getChildAt(i).dispatchTouchEvent(ev);
}
return true;
}
Now, keep the same logic that your custom views have, except they should all return false because your parent view will not receive the onTouch event unless they do as stated in my previous answer
note: with this implementation, the child view that the user actually touches will fire twice because the logic will go
fire child touch event -> return false -> fire parent touch event -> fire child touch event again
I know this question is very old, but I had the same problem and solved it by creating my own Layout to determine which child is actually touched.
I therefore iterate over the children of my custom layout and check if the user actually clicked on the view. The collision detection is handled in the custom view's onTouch() method. (Collision detection is done by intersecting a Region() with the event's x,y coordinates. For me this was convennient because I drew the custom view with a Path())
Here is a kotlin code snippet from my custom layout for better understanding:
class CustomLayout(context: Context, attrs: AttributeSet) :
RelativeLayout(context, attrs){
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
if(ev.action != MotionEvent.ACTION_UP){
return true
}
//Iterate over child view and search for the right child that should handle this touch event
for (i in childCount - 1 downTo 0) {
val child = getChildAt(i)
if (!viewTouched(child, ev)) {
continue
}
//Do something
Timber.d("Touched view: ${child.id}")
}
return true
}
private fun viewTouched(child: View, ev: MotionEvent) : Boolean {
child as OnTouchListener
//onTouch() does the collision detection
return child.onTouch(child, ev)
}

Detect which view your finger is sliding over in Android

While similar questions have been asked in the past they don't seem to really have been answered which might be due to confusion as to what's being asked.
Put simply, I'd like to detect which view is being entered as your finger slides over the screen. The best example of this in action is the soft keyboard on any android phone. When you press any key it shows up as a popup to tell you what letter is under your finger. If you now move your finger over the keyboard in a single gesture the various letters pop up as you move over the various letters of the alphabet.
What listeners are used for this type of behaviour. I've tried OnTouchListeners but they seem to be only when you 'touch' the button as opposed to 'finger past' them
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {doStuff();}
});
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
doStuff();
return false;
}
});
OnFocusChangeListener don't help either.
create a Layout
add Views to your Layout
set the setOnTouchListener to your Layout
override the onTouch method with the following:
public boolean onTouch(View v, MotionEvent event)
{
LinearLayout layout = (LinearLayout)v;
for(int i =0; i< layout.getChildCount(); i++)
{
View view = layout.getChildAt(i);
Rect outRect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
if(outRect.contains((int)event.getX(), (int)event.getY()))
{
// over a View
}
}
}
EDIT:
I saw keyboard. I guess, it just one view and coordinates of every letter is known. So you can easily compute which letter the user slides through
AND NOW THE ANSWER:
I'm not sure, but probably this code helps your.
It's so far away, I wrote it for me. But the idea is following.
If I remember right, there is no gesturedetector for views, but you can combine touchlistener of the view with geturelistener of your activity.
Once you've touched your view, you have
private GestureDetector mGestureDetector;
// x and y coordinates within our view
private static float sideIndexX;
private static float sideIndexY;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
...
mGestureDetector = new GestureDetector(this, new SideIndexGestureListener());
}
class MyGestureListener extends
GestureDetector.SimpleOnGestureListener
{
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY)
{
// we know already coordinates of first touch
// we know as well a scroll distance
sideIndexX = sideIndexX - distanceX;
sideIndexY = sideIndexY - distanceY;
// when the user scrolls within our side index
// we can show for every position in it a proper
// item in the country list
if (sideIndexX >= 0 && sideIndexY >= 0)
{
doStuff();
}
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
button.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
// now you know coordinates of touch
// store them
sideIndexX = event.getX();
sideIndexY = event.getY();
doStuff();
return false;
}
});
You may want to try GestureDetector.
http://android-developers.blogspot.com/2010/06/making-sense-of-multitouch.html
it's geared to multitouch, but this is a good start toward understanding android touch/gestures, next stop, api docs/samples
The simple answer is you can't - not like the iPhone when in accessibility mode.
Until Ice Cream Sandwich that is. It now has the iPhone-like capability of being able to identify elements under your finger without having to lift it.
It's fairly straight forward to handle this manually.
Using your parent layout as the onTouchListener (in the following example, I extend a RelativeLayout), you can check for collisions between a MotionEvent and the child Views using simple co-ordinate comparison logic:
/** Returns the View colliding with the TouchEvent. */
private final View getCollisionWith(final MotionEvent pMotionEvent) {
// Declare the LocationBuffer.
final int[] lLocationBuffer = new int[2];
// Iterate the children.
for(int i = 0; i < this.getChildCount(); i++) { /** TODO: Order. */
// Fetch the child View.
final View lView = this.getChildAt(i);
// Fetch the View's location.
lView.getLocationOnScreen(lLocationBuffer);
// Is the View colliding?
if(pMotionEvent.getRawX() > lLocationBuffer[0] && pMotionEvent.getRawX() < lLocationBuffer[0] + lView.getWidth() && pMotionEvent.getRawY() > lLocationBuffer[1] && pMotionEvent.getRawY() < lLocationBuffer[1] + lView.getHeight()) {
// Return the colliding View.
return lView;
}
}
// We couldn't find a colliding View.
return null;
}
Calls to getCollisionWith will return View references that may be manipulated arbitrarily.

Categories

Resources