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}
Related
I have an ordinary RecyclerView, and on top of it a transparent View that implements GestureListener, which basically have the same size of the RecyclerView.
The GestureListener will listen to scroll and fling gestures, and pass this MotionEvent to the RecyclerView underneath it.
I have already made the RecyclerView able to scroll and fling. However, I can't find a way to pass a click event down to the RecyclerView's items as well.
I already know that this is because ACTION_DOWN is consumed in the GestureListener. In fact, GestureListener has a onSingleTap() method for you to override, and this method was called whenever I perform a click.
According to this post, I tried to set an OnTouchListener to my itemView and listen to ACTION_UP events. However, the onTouch() method is never called.
Below is how I do it:
1. Create a callback in the transparent GestureListener
#Override
public boolean onSingleTapUp(MotionEvent e) {
if (scrollDetector == null) return false;
scrollDetector.onSingleTap(e);
return true;
}
Configure the callback in the activity, and pass the MotionEvent to the RecyclerView
#Override
public void onSingleTap(MotionEvent e) {
mRecyclerView.onTouchEvent(e);
}
Set OnTouchListener to the itemView in the adapter:
itemView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
v.performClick();
return true;
}
return false;
}
});
Using debugger, I can see that mRecyclerView.onTouchEvent(e) was called; but the onTouch() of itemView was not called.
So... How should I correctly pass the MotionEvent to the itemView?
You may ask - "Why do you place a GestureListener on top of the RecyclerView?"
This is because I need to change the height of the RecyclerView when the RecyclerView is scrolled. However, if I do this using RecyclerView's addOnScrollListener, the value of dy will fluctuate between negative and positive values, because dy is affected by its height as well. And the fluctuation will also be reflected to the UI.
Therefore I need a scroll detector that does not change its height when scrolled, and just pass the scroll and fling values to RecyclerView by programmatically calling scrollBy() and fling().
You should known that recyclerview's event.If recyclerview can move when you scroll views,it will call onInterceptTouchEvent() and return true to intercept event.So you can't get the ACTION_MOVE event.Maybe you should rewrite the recyclerview's onInterceptTouchEvent() and return false. Then you can get all the event in your itemView's methods.
Stupid me. I should use dispatchTouchEvent(MotionEvent e) instead of onTouchEvent(MotionEvent e).
However, this is not enough.
Simply calling dispatchTouchEvent(e) using the MotionEvent from GestureListener is not working, because that e is an ACTION_UP event.
To simulate a click, you need both ACTION_DOWN and ACTION_UP.
And itemView does not need to set OnTouchListener since you have already simulate
Code:
#Override
public void onSingleTap(MotionEvent e) {
long downTime = SystemClock.uptimeMillis();
long upTime = downTime + 100;
MotionEvent downEvent = MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN,
e.getX(), e.getY(), 0);
mRecyclerView.dispatchTouchEvent(downEvent);
MotionEvent upEvent = MotionEvent.obtain(upTime, upTime, MotionEvent.ACTION_UP,
e.getX(), e.getY(), 0);
mRecyclerView.dispatchTouchEvent(upEvent);
downEvent.recycle();
upEvent.recycle();
}
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;
}
OK, this might be trivial, but I can't figure out how to do it.
We have a container scrolling view, a subclass of ScrollView, and this view has a child view (among others) which should listen to touch events.
In particular, what I'd like to do is:
childView is clicked and MotionEvent.ACTION_DOWN comes;
check if that event is a scrolling event, i.e., check if that action would start a scroll on the scrollView;
if so, let the scrollView handle it and do nothing; if not, i.e. if the click upon childView did not start a scroll onto the parent view, do something.
Any ideas?
Pseudocoding, it should be something like:
ScrollView scrollView = ...;
View childView = scrollView.findViewById(...):
childView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
if (scrollView.onTouchEvent(event)) {
// event was handled by the view
return false;
} else {
// do something
return true;
}
}
return false;
}
});
As you can see I have not much insight on how motion events work.
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;
}
});