I have a ScrollView, inside that I have LinearLayout with 4 children. My problem is that my ScrollView consumes events and because of that I am not able to long press on my child views. I tried setting setLongClickable(false) but it is of no use, if I intercept touch events I'm not able to scroll my ScrollView.
Normally Android uses a long press to begin a drag in cases like these since it helps disambiguate when the user intends to longPress an item vs. scroll the item's container. But if you have an unambiguous signal when the user begins longpress an item, try getParent().requestDisallowInterceptTouchEvent(true) from the view when you know the user is beginning a press. This will prevent the ScrollView from intercepting touch events until the end of the current gesture.(check this link https://developer.android.com/reference/android/view/ViewParent.html#requestDisallowInterceptTouchEvent%28boolean%29)
Related
I have a ListView inside a ScrollView. I know I can intercept the touch events using the onInterceptTouchEvent method in the ScrollView. But once the child, i.e. ListView, starts consuming the touch event, onInterceptTouchEvent is not call. My problem is how can I transfer the touch event back to parent(i.e. ScrollView) once the ListView scroll has reached top. I want the scroll to be in continuation.
Suppose I'm scrolling the ListView and have reached the top of the ListView I want the scroll to continue so that I can scroll the parent, i.e. ScrollView. How can I achieve this?
You can check whether you are at the top of the listview, then return false from the touch event.
I have extended a FrameLayout and overriden the onInterceptTouchEvent() and onTouchEvent(). This custom Framelayout will be the root layout of my ListView rows.
My requirement is that, if I tap on a row in the ListView, the onItemClickListener should be called, if I scroll (up/down) the list scrolls as usual. However if I scroll (left/right) or swipe (left/right), the custom FrameLayout should take some action based upon which row I perform the action on.
My idea was that, I would override onInterceptTouchEvent, monitor the events and if I see that ACTION_MOVE has been called enough to make it a scroll/swipe then I take control and do the task. If it's a tap or some other gesture then let the default flow occur.
The problem I face now is that if my framelayout does not contain any touchable child, then I receive no calls post ACTION_DOWN. And if I receive the ACTION_DOWN in my onTouchEvent() so as to analyze the kind of gesture, then I have no control left to let the default flow occur if I calculate and find that the action was actually just a tap/vertical scroll.
Is there some way in which a child can get hold of the events (ACTION_DOWN and ACTION_MOVE) and if a condition satisfies then perform an action or else let the parent handle these same events?
Is there some other approach that I can take to satisfy this requirement?
I need to disable touchevent handling for a listview but allow it's children to receive clicks. I have a frame layout which has a mapview and the listview over it. When the list is empty, I want the map to handle all touch events but when the list is filled, I want the list items to receive clickevents.
You could intercept all touch events in a custom FrameLayout (your root ViewGroup) using onInterceptTouchEvent(): http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent).
What you do there is capture the MotionEvent.ACTION_DOWN event and decide whether the event is meant for the ListView or the MapView depending on whether the ListView is empty (touches go to the MapView) or filled and within the borders of the ListView (touches go to the ListView).
In both cases return true and capture the following ACTION_DOWN event in onTouchEvent() (still FrameLayout). That way all touch events up to ACTION_CANCEL will go to your FrameLayout's onTouchEvent().
Your FrameLayout's onTouchEvent() will dispatch all touch events either to the ListView or the MapView. The decision which views gets the events has been taken in onInterceptTouchEvent(), so you need to store the result of that decision somehow. That decision is valid between the ACTION_DOWN and the ACTION_POINTER_UP, ACTION_UP, ACTION_CANCEL events.
I'm not sure whether you want to disable all touch events for the non empty ListView that don't select a list item (flinging, scrolling etc.)? Because that would complicate matters considerably. Although I don't think that makes sense from a user perspective as list items not fitting the ListView's viewport could not be clicked because you can't scroll up or down.
Don't expect this to work easily. Understanding the flow of motion events and the interaction between onInterceptTouchEvent() and onTouchEvent() is challenging and making it work even more so. But I'm confident that this is a feasible way to solve your problem.
I have two scrollviews side by side, I want the user to be able to drag list items back and forth from left to right scrollviews. However, I can't find a way to handle the touch events. I can't set a touch listener for each scrollview seperately as the drag gesture gets dropped when passing from one to another. I tried creating an absolute layout over the top of both, which works from the drag and drop perspective, but it stops me from being able to scroll the scrollviews. Is there a simple solution to this? can anyone help me out?
Generally, onTouchListener returns a boolean that indicates whether the touch has been handled. It's up to you to decide whether the touch was handled or not. When the user touches a View, Android will call it's touch listener. If the touch listener returns true, then it regards the touch as handled then moves on. If the touch listener returns false, then it will go up one to the parent view (in this case whatever your ScrollView is). Then the parent view's touch listener is called and must decide how to handle the touch. It will keep cascading up the parent views until a true is returned or until it reaches the end.
In your case, you may have to decide what the user has to do in order to drag & drop vs. scrolling. Perhaps the user must do a long press on an item before he/she can drag it or something.
I have a ScrollView in which I have a quite long form, mainly using EditText elements. The problem is, that when the user scrolls around in this form, ScrollView changes the focus constantly. It seemed to me, that it assigns focus to the first element on screen when the user stops touching the screen, and the fling motion triggers.
How can I disable this?
Just a thought that you can make EditText as non-focusable elements. And when user will click on any item in ListView you can make that particular element focusable again.