I have a layout like
RelativeLayout_Parent
-> RelativeLayout_Child
both views having touch event.
But when I touch on RelativeLayout_Child, touch event for parent is also fired.
How to ignore parent view touch on child view touch?
Very simple, implement OnTouchListener over your child view, and upon receiving Touch Event just return true fro child, this will make sure touch event is not propagated to others.
child_view.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// this will make sure event is not propagated to others, nesting same view area
return true;
}
});
Related
I have one customView and customView added in scroll view. Now i want differentiate both touch events. My problem is when try to scroll, customView also getting touch event and when i try to change in customView, scroll view getting events.
How can we stop customView touch event when scrolling.
How can we stop scroll touch events when customView wants events.
Thanks in advance
You can set touch listener to child view and then in onTouch() event, you can block intercept touch event of parent.
i.e.
v.setOnTouchListener(new OnTouchListener() {
// Setting on Touch Listener for handling the touch inside ScrollView
#Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent scroll on touch of child view
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
About the second question, I don't know exactly what you're doing with customview but maybe you'd like to use click events instead because it's rather not user friendly to use different logic in ontouch and onclick as it will always fire up unexpectedly.
boolean isScrolling = false;
myScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() { #Override public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
isScrolling = scrollX != oldScrollX;
//for vertical scrolling
});
//then onTouchListener
if(!isScrolling){//Do operations on non scrolled state}
I have a movableView(moves with finger touch movement) of 400*400, it has a horizontal view at bottom (400*100). When I want to scroll horintalScrollView to see the list, my movableView is moving, but horintalSrollView is not taking any touchEvent.
I want it like, when I am touching horizontalScrollView, only it should scroll. And when not touching it and want to move my movableView it should move.
Any suggestions would be helpful.
Thanks
Try this logic...
scrollView.setOnTouchListener(new OnTouchListener() {
// Setting on Touch Listener for handling the touch inside movableView
#Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent move on touch of child view
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
I created custom View similar to SeekBar. Now when I touch regular SeekBar and slide it work even I move finger out of SeekBar. But when I touch my custom View and move finger out of it ScrollView start moving and my View do not recieve MotionEven any more.
How can I make it acting same way as SeekBar?
You need to disable touch event of the parent view when the touch event is cached by you view, like this:
#Override
public boolean onTouch(View v, MotionEvent event) {
// Disallow the touch request for parent scroll on touch of child view
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
I have a list view whose item is a linearlayout which has a button as it's child view. I want the ontouchLIstener of the linearlayout to work. I don't want to use onInterceptTouchEvent. Is there a way a I can pass on the touch form the button to the parent listview. I tried this
- returning true from the button's onTouchListener
private View.OnTouchListener buttonListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.i(TAG, "Button On Touch");
return true;
}
};
But this does not work. It does not pass on the touch event to the linearlayout's onTouchListener.
There must be someway it should work.
The chain of events for a View group works like this - The dispatchEvent is called. Then dispatchEvent calls onInterceptTouchEvent. if it returns false, then the touch events are passed on to the children of the ViewGroup. If any of the children consume the event (in this case the button consumes the event) i.e if they return true then the motionevent is not passed on to other methods. Since the button is clickable it returns true in this case. If the onInterceptTouchEvent method returns true then the child views are not given the motion event and instead that ViewGroup's onTouchListener or onTouch method are called. Hence to pass on the touch event to the parent's (View Group) onTouchListener make sure to return true in the onInterceptTouchEvent method of the Parent (ViewGroup). You don't have to override onDispatchTouchEvent()
#Override
public boolean onInterceptTouchEvent(MotionEvent motionEvent) {
Log.i(TAG,"PARENT.onInterceptTouchEvent");
return true;
}
For more details about how the touch navigation is done, please see this stack post
Set your button clickable property to false, using:
button.setClickable(false);
Then in onTouch of button:
return false;
Note: This behavior is specific to button (and any other view that has clickable property set to true) that even if you return false from onTouch it will not propagate event to the parent and onClick method of the button will be called anyway.
EDIT: Another way is extending ListView class and overriding onInterceptTouch:
public class CustomListView extends ListView {
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// here you can listen for button touch events
}
}
I have a one RelativeLayout and this layout is having nearly 10 views in it.
I have set OnTouchListener to this Layout and doing some work in it and returning true.
this listener is working fine when I touch the layout where there are no View (mean on Empty area). If I touch on child views of this layout, this listener is not firing...
and from the documentation, I understood that we can override onInterceptTouchEvent() by extending ViewGroup (so here RelativeLayout) and handle touch events before child views consume this event...
this will do a trick, but I need to modify many xml files where I need this functionality by replacing RelativeLayout with my CustomRelativeLayout.
so my question is:
is there any way to handle touch event for RelativeLayout (ofcourse ViewGroup) before child views in RelativeLayout consumes event? I don't want to extend RelativeLayout...
Try to override
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
of Activity.
This method is the first that process touch events.
But in this case you need to work with current coordinates of views
While not necessarily being ideal, this works well for smaller layouts that won't have dynamic content.
In xml, set android:clickable="false" to all descendants of the ViewGroup in the layout (including nested ViewGroups and their children). Each child that gets clicked on will then propagate the click to its parent, eventually getting to the ViewGroup's default touch handlers. Make sure to set root ViewGroup, where you want to get the click events as android:clickable="true" or viewgroup.setClickable(true)
If you add views dynamically, make sure to call view.setClickable(false); before adding it to the view hierarchy.
Try add onTouchListener to RelativeLayout
RelativeLayout rl = (RelativeLayout) findViewById( R.id.relativeLauout );
rl.setOnTouchListener( new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// do something
return false;
}
});
or use method onTouchEvent from Activity
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return super.onTouchEvent(event);
}
Try to return false in the onTouchEvent() method of child views when processing ACTION_DOWN event. So the forwarding touch events will not be sent to child views, aka event not consumed.
You can simply set in your xml:
android:clickable="true"