Android - Reverse listview as message display - android

I've got a little question for my Android App.
I searched for a long time but found nothing about my problem.
Scenario : I've to display a revert listview (as Facebook Messenger).
And when the user scrolls to the top, load more messages.
Problem : After notifiyDataAsChanged() call, the scroll is not the same!
I want to conserve exactly the same position as before loading.
I tried that code :
// save index and top position
int index = list.getFirstVisiblePosition()+result.size();
View v = list.getChildAt(index);
int top = (v == null) ? 0 : v.getTop();
// ...
// restore
list.setSelectionFromTop(index, top);
But the scroll is not exactly the same after loading.
Have you got an idea ?

I think you should look into using TranscriptMode and StackFromBottom with your listview:
android:stackFromBottom="true"
android:transcriptMode="normal"
By setting the transcript mode to normal it will scroll to the bottom only if the last item was already in view. That way your users can view the previous list view items without interruption when you call notifydatasetchanged.

do like this:
Collections.reverse(YourList); // ADD THIS LINE TO REVERSE ORDER!
YourList.notifyDataSetChanged;

I fixed this by using the same code as you included but I update the index variable by the number of items I add to the adapter before restoring the position. Seems to do the trick.

For Kotlin is more easy just
myList.reverse()

Related

Android RecyclerView best practice for displaying items

I have a reyclerview in which every time I add an item I add it at index 0, Usually when you add an item a given index you can do it like so
mAdapter.add(0, item)
mAdapter.notifyItemChanged(0)
the problem is the item will be added to index 0 but the user will have to scroll to view it, of course, there is a solution which is by simply doing the following
messageAdapter.add(0, item)
messageAdapter.notifyDataSetChanged()
the problem here is that by calling "notifyDataSetChanged()" the item will appear all of sudden inside the list which I don't like I want to have a nice and smooth animation for when the item is added, another solution is to manually smooth scroll the recyclerView whenever an item is added using our first code, this solution is the best but it has some problems.
when the user is viewing item at index 999 and a new item is added the view will be scrolled to index 0 which can be kind of annoying for the user, the solution is simple for this problem, we can check if the item at index 0 is visible if it is, then scroll to index 0, this is the perfect solution for my problem.
So my question is, is there any other way to implement the functionality that I want to achieve without having to do that work? I would like to know what the simplest way is, thank you in advance!
Try using diff util it will be better for performance for updating recyclerview
https://blog.mindorks.com/the-powerful-tool-diff-util-in-recyclerview-android-tutorial

How to add items at top of ListView with scrolling without stuck?

I am working on chat application in which I have to manage thousands of chat messages list by paging but my problem is that when I am adding items at the top of ListView adapter during fast scrolling and applying setSelectionFromTop(index, y)...by this my list scrolling getting stuck on index...
adapter.setData(listChatMessage);
adapter.notifyDataSetChanged();
View v = threadList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
listView.setSelectionFromTop(index, top);
So how can we add items at the top of ListView with scrolling without stuck. What approach should I use.
Can anyone suggest me?
If im not wrong take look at this
How to get the scroll speed on a ListView?
then set listView.fling(int velocityY)
After a long search I found satisfactory post.
https://chris.banes.me/2013/02/21/listview-keeping-position/

How to programmatically snap to position on Recycler view with LinearSnapHelper

I have implemented a horizontal recyclerView with LinearSnapHelper, to implement a UI input that selects a particular configuration. Kinda like the old school number picker/selector or spinner. The item in the center is the selected position.
it works fine and all, but here's the problem. On initial start up, I need to programmatically set the position of the recycler view such that the selected item (the index of which was loaded from disk) is position in the center.
.scrollToPosition() wont work becuase it places the selected item in the begining.
now I know I can do all the math and calculate the x coordinate and manually set it, but thats a lot of redundant work because LinearSnapHelper is already doing this, and I feel like there should be a way to just reuse that logic, but with actually initiating a fling.
I need something like LinearSnapHelper.snapToPosition()
More general solution:
First scroll RecyclerView to make target item visible.
Than, take the object of target View and use SnapHelper to determine
distance for the final snap.
Finally scroll to target position.
NOTE: This works only because programmatically you are scrolling at the exact position & covering the missing distance by exact value using scrollBy instead of doing smooth scrolling
Code snippet:
mRecyclerView.scrollToPosition(selectedPosition);
mRecyclerView.post(() -> {
View view = mLayoutManager.findViewByPosition(selectedPosition);
if (view == null) {
Log.e(WingPickerView.class.getSimpleName(), "Cant find target View for initial Snap");
return;
}
int[] snapDistance = mSnapHelper.calculateDistanceToFinalSnap(mLayoutManager, view);
if (snapDistance[0] != 0 || snapDistance[1] != 0) {
mRecyclerView.scrollBy(snapDistance[0], snapDistance[1]);
}
}
});
Try calling smoothScrollToPosition on the RecyclerView object, and passing the position index (int)
mRecyclerView.smoothScrollToPosition(position);
Worked for me with a LinearLayoutManager and LinearSnapHelper. It animates the initial scroll, but at least snaps the item in position.
This is my first post on the stack, hope it helps :)
I have a recyclerView which I have added padding at the left and right with dummy views in the adapter. So that the first "actual" item can be snapped to.
I couldn't get smoothScrollToPosition(0) to work though for the initial snap. I used the following
recycler.scrollBy(snapHelper.calculateDistanceToFinalSnap(binding.recycler.getLayoutManager(), recycler.getChildAt(1))[0], 0);
Isn't the nicest looking way, but seems to work!

RecycleView: how to go to a row without scrolling

If the recyclerview has a list of items and I want to go to a specific row immediately when user enters the UI, so I don't want the user to see it scroll to reach that row. Is it achievable?
Thanks.
You can use method scrollToPositionWithOffset (int position, int offset)
Scroll to the specified adapter position with the given offset from
resolved layout start.
See documentation
Example:
//Scroll to item position 2 with offset 0
RECYCLERVIEW_LAYOUT_MANAGER.scrollToPositionWithOffset(2, 0);
Hope this will help~
I would say it is impossible.
RecyclerView#scrollToPosition causes sort of animation because it does not know the height of all rows initially. Not all items are loaded immediatly but one by one as you scroll down the list.
I use ListView and I solved the issue by calling setSelection(position)

Android ListView y position

It seems like ListView doesn't expose its y-position in the same way a ScrollView does. In other words: I need to remember the exact position the ListView was scrolled to and set it when I return to the activity.
Just to clarify: I don't need the selected item... that's pretty straight forward. I need to restore the exact pixel-wise y position on the ListView.
Thanks!
I've used this successfully when saving (in onSaveInstanceState) and restoring (onCreate), when switching orientations:
Saving:
int savedPosition = list.getFirstVisiblePosition();
View firstVisibleView = list.getChildAt(0);
int savedListTop = (firstVisibleView == null) ? 0 : firstVisibleView.getTop();
Restoring:
if (savedPosition >= 0) { //initialized to -1
list.setSelectionFromTop(savedPosition, savedListTop);
}
This will precisely save the Y position. Well, it misses by a few pixels every once in a while.
When you are returning from another Activity, the ListView will remain scrolled to its original position that it was at when you left that ListView Activity. If you are updating the contents of the list make sure you just use notifyDataSetChanged() on the adapter, do not re-assign the adapter - this will reset the list to the top.
Check your onResume method in your ListView Activity, it might be re-assigning a list adapter.
If you need to remember an arbitrary scroll position that doesn't rely on the Activity stack, I am willing to bet that isn't possible besides just saving the current selected or first visible item. A ListView does not have a defined height. It is relative to both the number of items and content of those items.
Parcelable state = list.onSaveInstanceState();
// do stuff
list.onRestoreInstanceState(state);
Is the only correct way I know of to maintain exact position of a list. The above solution that's marked as correct bumps up/down a few pixels so not really the most professional solution.

Categories

Resources