Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android onTouchEvent for custom view

Tags:

java

android

I created a service that displays a custom View inside a custom LinearLayout. The service works fine, and the View is shown on the screen, but I cannot get the View or the LinearLayout to receive any touch events (I just want either one of them to receive touch events, I don't care which). This is what I have:

MyLayout.java

public class MyLayout extends LinearLayout {

    public MyLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public MyLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyLayout(Context context) {
        super(context);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        onTouchEvent(ev);
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Toast.makeText(this.getContext(), "Touched layout", Toast.LENGTH_SHORT).show();
        Log.d("TOUCH", "Touched layout");
        return true;
    }
}

MyView.java

public class MyViewextends View{

    public MyView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context) {
        super(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Toast.makeText(this.getContext(), "Touched View", Toast.LENGTH_SHORT).show();
        Log.d("TOUCH", "Touched View");
        return true;
    }
}
like image 357
yawers Avatar asked Dec 31 '15 18:12

yawers


2 Answers

From the SDK Documentation:

onTouch() - This returns a boolean to indicate whether your listener consumes this event. The important thing is that this event can have multiple actions that follow each other. So, if you return false when the down action event is received, you indicate that you have not consumed the event and are also not interested in subsequent actions from this event. Thus, you will not be called for any other actions within the event, such as a finger gesture, or the eventual up action event.

You need to return true when the ACTION_DOWN event is triggered to indicate that you are interested in the subsequent calls relating to that same event.

If you need to write an Android onTouchEvent method inside a View class, here’s some example source code (boilerplate/skeleton code) that shows how to implement this method, including how to use the MotionEvent in the method, and how to get the x and y location of the touch event:

public boolean onTouchEvent(MotionEvent event) {

    int eventAction = event.getAction();

    // you may need the x/y location
    int x = (int)event.getX();
    int y = (int)event.getY();

    // put your code in here to handle the event
    switch (eventAction) {
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_UP:
            break;
        case MotionEvent.ACTION_MOVE:
            break;
    }

    // tell the View to redraw the Canvas
    invalidate();

    // tell the View that we handled the event
    return true;

}

I commented the code, and I think it shows the most common way this method is used, so I won’t bother to add any explanation here. I showed how to get the x and y location of the touch event because you’ll generally want to check to see where the event occurred.

So, in summary, if you wanted to see an example Android onTouchEvent method (in a View class), I hope this example is helpful.

ref : http://alvinalexander.com/android/android-ontouchevent-example-method-view-class

like image 178
Mohammad Salem Avatar answered Oct 02 '22 11:10

Mohammad Salem


Your View is not receiving any touch events because your custom LinearLayout is blocking the events as it does not dispatch the events to its child Views.

I'm not quite sure why you are overriding the methods onInterceptTouchEvent() and onTouchEvent() in your MyLayout, but if you do not require them, I would suggest to remove them both, so the layout has its default behavior regarding processing touch events.

If you really need them, you may have to call the super methods of each:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return super.onInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    Toast.makeText(this.getContext(), "Touched layout", Toast.LENGTH_SHORT).show();
    Log.d("TOUCH", "Touched layout");
    return super.onTouchEvent(event);
}
like image 31
Floern Avatar answered Oct 02 '22 12:10

Floern