When I add a new list item, with the keyboard still open, the list item appears behind the keyboard and is thus invisible. How do I scroll it automatically down to it becomes visible?
Keep in mind that I have already solved the following:
When opening keyboard scroll the RecyclerView to make the last item visible: Solved
The last remaining issue is when the keyboard is already open. It works fine when I open the keyboard for the first time. It's when I hit "send" that the item is added behind the keyboard and when I want it to scroll up
I hit "send message"
This is what happens. It's hidden behind the keyboard
Set your LayoutManager to reverse layout to have the RecyclerView retain its positioning against its bottom edge instead of the top one:
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setReverseLayout(true);
myRecycler.setLayoutManager(layoutManager);
There should be no need to automatically scroll to the last position of your Adapter anymore so, if you previously had code to do so, you should remove it.
You will also have to reverse the order of the data set in your Adapter to match the ordering you originally had (If your data was originally sorted Ascending, then you should change it to Descending).
For your case, you would want to sort by Descending time to have the items arranged by most recent at the bottom and oldest at the top of the RecyclerView.
And, if you're directly adding to the Adapter's data set, you should add to the beginning of the Adapter's list:
myDataList.add(0, myNewItem); // Add to the beginning of the list shifting previous items over
notifyDataSetChanged(); // Notify the adapter to refresh
Related
I am trying to scroll and request focus to an off screen element from a recycler view. I have a list of 15 languages. When app starts the user can select one language from the recycler. Then if the app starts again the recycler scrolls and request focusto that item.
But imagine the user selects the last language from the list which is not showed in the recycler when the app starts. How to scroll and therefore reqeust focus to that element which is not currently showed in the recycler?
I expected to do something like recycler.scrollToPosition(14) and then scrollToPosition(14) , but the index is outof bunds... I guess thats because the element is not created yet. Any idea?
I had similar scenario and below code worked for me:
(rv_your_recycler_view.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position, offset)
Just set offset to 0 and position to 14, this will get you last item.
P.S. If it doesn't work check if your recyclerview's bottom constraint tied up to parent's bottom.
app:layout_constraintBottom_toBottomOf="parent"
If you try to scroll and set the focus at the same time then it may fail. While the scrolling will proceed, the request for the focus will fail if the item is not yet present in the RecyclerView. (As you state.)
The solution is to separate the two activities. Scroll to the position as you do now, but set the focus when the item is bound to the view holder in the adapter. This will require you to keep track of which item has the focus so that it can be referenced in the adapter.
I need to enable click listener on RecyclerView item only if it is completely visible otherwise click listener should not work. Is there any way to detect whether an adapter item is completely visible or not when user click on it?
What you are looking for can be found here
You could make some logic using LayoutManager api to get last completely visible item position in RecyclerView onScrolled method:
((LinearLayoutManager) vYourRecycler.getLayoutManager()).findLastCompletelyVisibleItemPosition();
From the documentation: Returns the adapter position of the last fully visible view. This position does not include adapter changes that were dispatched after the last layout pass.
I'm trying to create "sticky headers" on a RecyclerView (which uses a LinearLayoutManager) but now I'm facing a problem. When I click on one item of the list, a new item is automatically inserted just below it and the RecyclerView's default animation is shown (the one which smoothly adds and shows the new item). When I tap the initial item again, this new added item is removed, and the RecyclerView's default animation is shown again (the one to slowly hide the removed item).
I have completed all the sticky headers functionality but now my problem is that when I click the last list item and the hide default animation is shown (with a scroll up), my sticky headers don't work. I need to know (and here is were I'm stuck) how to get notified while this RecyclerView animation is being performed when adding/removing items. I need to get notified with all the animation steps, not only the start and end ones.
So far I've tried to use a RecyclerView onScrollListener and a ViewTreeObserver (attached to the added/removed view) but neither worked. If someone could give me some help, it would be really appreciated.
Thanks in advance to all the Stack Overflow community
I have a list of items. These items are sorted by date. Items with date before now ("old" items) should not be visible when user opens application but user should be able to see them by scrolling list to top.
I find position of first item with date in the future ("new" item) and call recyclerView.scrollToPosition(position).
I also tried layoutManager.scrollToPositionWithOffset(position, 0).
This works if there are many "new" items in the list.
But if there are too few items (for example, one "old" and one "new") then these methods do not work.
How can I scroll list programmatically to item at given position to place this item on top regardless of how many there are items in the list?
Initially, provide the RecyclerView with a dataset that has only the future events.
Set an onTouchListner on recyclerView to detect upward scroll. If findFirstCompletelyVisibleItemPosition() returns the first index when you detect an upward scroll, it means an upward overscroll. Then, change the data set to include the old entries. Then, use adapter.notifyDataSetChanged() to notify the adapter of the dataset change and list will be redrawn.
NOTE :
When you set onTouchListner on the RecyclerView make sure you
don't absorb the touch event [onTouchEvent() should return false].
Once, you've detected an upward overscroll for the first time,
you can set a flag to indicate that you don't need to change the
dataset for future touch events.
How can I stop RecyclerView from scrolling to the bottom of the list whenever I add items?
Even when I insert something at the top of the list and call notifyDataSetChanged or notifyItemInserted the list scrolls to the bottom.
The one feature that works as expected is notifyItemRemoved(index)
I think I was calling notifyRangeInserted() with the entire list and that was scrolling to the end of that range.
If you're having similar issues, just cut the Adapter functionality back to its bare essentials and build up from there.
The problem was I had an item in the list, a ProgressBar to indicate that data was loading, but when the new items loaded I added them to the list, this moved the "focused item," the ProgressBar down and if there were enough items to move it off the screen then the RecyclerView would scroll down to keep it on screen. The problem being 1. I didn't want it to maintain "focus" and 2. The very next thing I did was remove the ProgressBar from the `Adapter.
So the solution is to remove the ProgressBar or other items before adding items earlier positions in the Adapter.