Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to obtain the underlying view from a MotionEvent?

Tags:

android

My GestureListener class receives a MotionEvent in methods like onSingleTap() or onFling(). Is there a way to determine the underlying view from this event?

Background: I have a LinearLayout which contains many child views. This LinearLayout has a touch listener on it, which calls to a gesture detector. So when the user does a gesture on any child view, the LinearLayout's gesture detector receives a MotionEvent. But the problem is, because there are many children, I need to know exactly which child the user tapped on. But I can't find a method that converts a coordinate to a view. Is there a way to do this?

An ugly solution: The children are added dynamically. So I can keep all the children in a list, then when a MotionEvent comes, I can iterate through the list and see if the point is inside a child. But I don't like this idea. Is there a better way?

like image 312
wwyt Avatar asked May 23 '11 03:05

wwyt


People also ask

What is Action_up and Action_down?

ACTION_DOWN : When finger or object first comes in contact with the screen. The event contains the initial starting location of a gesture. ACTION_UP : When finger or object lifts from the screen. Contains the final release location of a gesture.11-Feb-2022.

Which motion event does a gesture start with?

A gesture starts with a motion event with ACTION_DOWN that provides the location of the first pointer down. As each additional pointer that goes down or up, the framework will generate a motion event with ACTION_POINTER_DOWN or ACTION_POINTER_UP accordingly.

What is a motion event?

Motion Event Explanation Motion events describe movements in terms of an action code and a set of axis values. The action code specifies the state change that occurred such as a pointer going down or up. The axis values describe the position and other movement properties.

Which method you should override to control your touch action?

To make sure that each view correctly receives the touch events intended for it, override the onInterceptTouchEvent() method.


3 Answers

Are you certain you want the touch listener on the layout? Why not have each view have a touch listener?

Let's assume you have a bunch of switches that require flings to toggle. The switches control a monster. You could have each switch (your View) have a touch listener that passes the switch to the monster. Now the monster can handle each view differently.

Something like this:

brightnessSwitch.setOnTouchListener( new View.OnTouchListener() {
  boolean onTouch(View v, MotionEvent event) {
    monster.toggleBrightness();
    return true;
  });

You could even pass the MotionEvent on to the monster. (Or if you wanted a single type of TouchListeners, you could pass both the view and the event to the monster, but you lose information about which switch is which.)

like image 50
idbrii Avatar answered Oct 01 '22 04:10

idbrii


Since you use an ontouchlistener on your top view group, the LinearLayout, to handle motionevents, if the return value of ontouchlistener is true, the even will not be dispatched to any other targets. So probably you need to use the ugly method. I'm current engaged in this issue and find it really annoying.

Otherwise, set ontouchlistener for each childview as needed.

like image 44
Neo Avatar answered Oct 01 '22 02:10

Neo


If you can, use a ListView or GridView over your base layout (Linear or otherwise) and under your child views.

Then...

int pos = getGridView().pointToPosition((int) me.getX(), (int) me.getY());

View v = getGridView().getChildAt(pos);

You can also listen to the children carefully managing the boolean you return when handling.

like image 34
kandinski Avatar answered Oct 01 '22 03:10

kandinski