When I long-click on an item in my RecyclerView to select it (i.e., select the initial item in the selection list managed by SelectionTracker), an ActionView expands at the top of the display screen and forces all other Views downward a distance equal to the ActionView's height. This is desired behavior.
However, if the y-coordinate of the long-press is within a distance equal to the ActionView's height from the top of the item's View, then the item above that item will also be selected, which is not desirable. This is happening because, after the downward translation of all Views, the SelectionTracker sees that other item as being under the long-press coordinates and automatically determines that it, too, should be selected. This is equivalent to the user having immediately dragged the pointer up a distance equal to the ActionView's height had the ActionView not appeared.
There are two approaches I've thought of to deal with this problem:
The first involves intercepting the click and translating its y-coordinate down a distance equal to the height of the expanded ActionView, but only under the right conditions (i.e., only when there are no existing selections and only if the clicked-on item is not at position 0 in the adapter). There are several problems with this approach, but I was curious to see if it would work. (It didn't.) One class of problems centers around how to get the same coordinates that SelectionTracker uses. These are coordinates within the RecyclerView's local coordinate system (aka: "View coordinates"), but there's no way to get to them through the SelectionTracker API. They are, however, used by the ItemDetails lookup's getItemDetails(MotionEvent) method. Unfortunately, modifying the coordinates of the input MotionEvent has no "downstream" effect on the selection/non-selection of subsequent items.
The second approach was to write a custom SelectionPredicate. I believe this would work to prevent the selection of the second item, because I think the selection logic within SelectionTracker is subject to the logic within the SelectionPredicate. However, the problem I'm having with this approach is, again, getting access to the coordinates used internally by the SelectionTracker. With those coordinates, I could determine when the conditions exist that would result in the unwanted, automatic selection of that second item and, therefore, I could return false from the SelectionPredicate callbacks where appropriate.
Does anyone have a suggestion for how to address this problem?
Related
I created a drag and drop gridview (using an OnDragListener). Grid items can be dropped upon one another. However, I also want to be able to re-order them. I implemented this, but there is a major issue left standing: the user control part.
When I drag around my shadow object I want the items to make space for my dragged object while I am dragging it around. I already implemented the moving of the other items, but I cannot seem to figure out a way to find out IF/WHEN I am in between two items. I get drag events when I hoover ABOVE an item, but not in between then. The gridview does not get any onTouchEvent calls when I am dragging, not even onInterceptTouchEvent calls.
Does anyone know a way in which I can implement this?
I already tried:
Implementing onTouchEvent and onInterceptTouchEvent in the gridview. Problem:
The gridview does not get any onTouchEvent calls when I am dragging an item, not even onInterceptTouchEvent calls.
Setting another draglistener on the whole gridview. Problem: ACTION_DRAG_LOCATION gets only called a few times, not on every move (location change), as is documented (!!).
I removed the padding between the grid items and gave the items themselfes some extra size, so that you are never inbetween items, but also on the side of one of the items. I detect when I'm at the side of an item and move the items accordingly to make space for my dragged item.
I have a Gallery based View with a negative spacing between elements, so that one zoomed out behind the previous, i.e. 'carousel'. Zooming and carousel effect is achieved by Camera transformation.
The problem arises when I try to click right side of foreground item and what I really get is click on item behind it (always to right of it)
Let me enumerate what I've already tried:
setChildrenDrawingOrderEnabled(true);
z coordinate of background item is obviously greater then foreground
one
getChildDrawingOrder was overridden as many ways as possible (and I
found out that it doesn't play any role at all - touch events don't
depend on visibility order of views)
Seems like next(right) child has greater index and therefore a priority of handling UI events, and my z-coordinate/drawing order manipulations don't change anything.
So question: how to make foreground item responsible for all click events on it?
In my application I have a custom gallery which shows some LinearLayouts (custom components to be precise, but that doesn't matter I think).
What I want is that if I scroll in between to items that it stays there and doesn't select the closest one (as it does by default).
If I override the onTouchEvent and in the case of an ACTION_UP ignore the event I get the desired result, BUT then I lose the onFling (the scrolling doesn't continue but stops immediately).
Then I think I'll have problems with my indicator of the position as I will probably lose the OnItemSelected handle, but I'm not sure of that (of course).
every suggestion is welcome.
I have a ListView in which the user can drag&drop list elements to reorder the list (android 3.0). However, I have to handle the case when the list is long, and the user has to be able to scroll it during dragging an item. So I've put two scroll-areas onto the screen, one at the top and one at the bottom. When the user drags an item onto these, the ListView should start to scroll up/down with a constants speed, as long as the dragged item is in these areas.
How can I achieve this scrolling with ListView?
I've tried the smoothScroll...() methods but they need a specific position in the list to scroll to, or a specific distance to scroll by. The standard scrollBy...() methods don't work either, they scroll the ListView, but don't appear to invalidate is properly, so the appearing rows don't get rendered.
Any ideas?
You could try listView1.smoothScrollByOffset(int viewPosition). This way you could make the listview scroll up and down by an interval of 1+ views.
You could try smoothScrollToPositionFromTop(int position, int offset, int duration) with varying duration depending on the position where to scroll, like say
int duration = position*100;
I have a ListView in my Android application. The individual views in the list are a little bit smaller than the size of the screen.
I want the list to always show one item centered in the screen, with just a small sliver of the previous and next items showing above and below it.
When the user scrolls, I need to reposition the child view at position 0 or 1 (depending on which way they are scrolling). Currently I am doing this by calling "setSelectionFromTop" in my onScrollStateChanged method. This works, but the transition is immediate, not smooth. It is jarring and confusing in a lot of cases.
What's the best approach to fixing this? I want to animate the process of scrolling the list into the position I want, but I can't find any methods in ListView or its superclasses that let me directly control the scroll position of the entire list.
I think I could animate it using multiple calls to setSelectionFromTop(int position, int y) with progressive values of y, but I don't know how to determine the initial value of y. Is there some way to get that by interrogating the view object at the designated position?
Another challenge I have in front of me is that I want to animate the removal of an item from the list - by having it either disappear or slide away to the left, and then having the surrounding views move up and down to fill the space. Is there a straightforward and reliable way to do this with a ListView? Should I just give up on the ListView and write the whole thing as a custom view from scratch?
Thanks.
This definitely should be possible. Does smoothScrollToPosition() work?
Otherwise, you can try simulating the touches using TouchUtils.