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.
Related
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)
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 have an app that inside onItemLongClick opens a dialog. I want the user to have a better experience so I want the possibility to choose and item in the dialog without having to raise his finger but I can't understand how to make a onTouch listener that will get the MOVE MotionEvent. can anyone tell me how to do this?
Thanks,
Benny.
Any onTouchListener will get move events, unless the moves are stolen from it. Given you're in an onItemLongClick, are you part of a ListView? If so, you'll get ACTION_CANCEL whenever the listview decides to take the touch events away from its children to scroll with, and you won't receive further moves (or even an up).
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.
The problem is the the scrolling will intercept with touch event has set to the parent layout.
Can I keep the onTouch event with the scroll in ScrollView ?
This is a very tricky part. There is an overriden method from Activity which is: public boolean onTouchEvent(MotionEvent event)
This is the general method that interprets all the touch events from the whole screen. And you could say, "ok, I can implement this and I am good to go..". And here comes the difficult part on how android works.
As you know every View has its own onTouchEvent() method that you could implement in order to add some custom implementation. So which method will listen? The ScrollView or the Activity? It appears that these touch events go from the "inside" elements to the "outside" elements. I mean parent-child relations.
Another thing to take into account is that the onTouchEvent method returns a boolean. This boolean parameter determines whether the touch event should go one level up or it is handled by the current View. Meaning that if you have a CustomViewA that implements the onTouchEvent() and CustomViewB implementing its own touch event, and the A is a child in B then the touch event would go through A first and if it is not handled it would go to B.
So basically yes it could be done. It depends on what touch event you wanted to do.
So in our case, the ScrollView returns true when the touch events are a horizontal. The activity's touch event will be handled only if the ScrollView touch event is not handled by itself then you are fine. Otherwise you have to override and implement the on touch event of scroll view and in some cases you have to return false so as for the whole layout to implement it. Good luck with the last part. I started to implement a fling effect but came up with some difficulties so I have implemented a 2 finger move with scroll view in it and it works like a charm.
This is about a week of research and experimenting and it is an overview of what I came up with. if you find anything else please let me know. Hope it helped.