Android 2.3 maintain ListView position when using Fragments - java

I have been trying to find a solution to this. How do I maintain the ListView position when I am using Fragments and someone rotates the device.
The rotation itself resets everything and it's back to 0 again. I can get it to work with the multiple examples when I am using normal Activities, but how do I do it when I am inside a specific Fragment?

Make sure that you do not call setAdapter() again on rotation or after any operation you do. Always call notifyDataSetChange() and your list will remain at the same point
Other workaround can be that you save the position of the current list item and call setSelection(position) for what you want to keep

You d have to store some kind of view tag or position number in a bundle on your on pause and in your on resume check if the value is null. If it's not set the list view to said position.

Related

RecyclerView item deletion not animated properly

I've got a RecyclerView which contains items, obviously. It uses the DefaultAnimator for all its animations.
When deleting an item, the deletion is animated, but not as it should be. The issue is that it seems like the size of the list is reduced by one first, then the clicked item is deleted and afterwards all items below are moved upwards by one. Take a look at this short video to see what I'm talking about.
The code used for the removal of a item is the following:
MainActivity.events.events.remove(listItems.keyAt(0));
notifyItemRemoved(listItems.keyAt(0));
Where MainActivity.events.events contains the data for the items and listItems.keyAt(0) contains the currently selected item.
What I've tried yet (none of this worked):
Made sure there's no other call which interrupts the animation (like notifyDataSetChanged()).
Implemented the above code directly into a onClickListener for the items inside the adapter.
Implemented the data directly into the adapter instead of a different class.
Replaced the position with getAdapterPosition() or a fixed value (i.e. 0)
Used notifyItemRangeRemoved() after notifItemRemoved().
Hint: I've got the animation to work previously, but as of today it doesn't work anymore.
EDIT:
If I remove the actual removal command (i.e. MainActivity.events.events.remove(listItems.keyAt(0));) from the code snippet given above, the animation is played correctly, but the element then isn't actually removed, so this doesn't solve the problem at all.

Open recyclerview from the fifth element

I have a standard recyclerview with 20 elements in a fragment. Now what I want is to open the view from the fifth element. Please note that I don't want to smoothscrolltoposition. I want it to be open from the fifth element.
UPDATE:
I want it to be opened with this without scroll-
I want a functionality where the user can still scroll up-
And I have already populated my recyclerview.
You can try any of these two methods according to your use case. It won't be a smooth scroll.
If you want to scroll to a specific position but that position is the adapter's position and not the RecyclerView's item position. You can only achieve this through the LayoutManager.
recylerView.getLayoutManager().scrollToPosition(adapterPosition);
If it is RecyclerView's item position:
recylerView.scrollToPosition(itemPosition);
Hope this helps you out.
References: 1 and 2.
NOTE:
Try to call this before onStart callback method. Because by that time, activity/fragment is not visible to the user and thus scroll won't be visible.
Example - If the RecylerView is inside an Activity, call it from onCreate.

Nested Fragment not retaining its state

I have a Fragment A (say) which contains a FragmentPagerAdaptor, which further contains Fragments (having list view).
When I click on a list item, I replace the complete Fragment A with another fragment (say B), I have also added the transaction for Fragment A in the back stack; now when I press the back button from B, the list in the child Fragment of A gets recreated and scrolled to top.
I want to retain the state(scroll) of the list, I tried storing the scrollY of the list and setting it again, but it's inaccurate and the list takes some time to initialize, also it takes time to scroll (since the list can have thousands of items).
I came across this link to resolve the issue:
http://ideaventure.blogspot.in/2014/10/nested-retained-fragment-lost-state.html
but setting the setRetainInstance(true) in child Fragments crashes the app saying:
java.lang.IllegalStateException: Can't retain fragements that are nested in other fragments
It is also a known bug in google forums:
https://code.google.com/p/android/issues/detail?id=74222
Any kind of help will be greatly appreciated!
I want to retain the state(scroll) of the list, i have tried storing the scrollY of the list and setting it again, but it's inaccurate and the list takes some time to initialize, also it takes time to scroll(since the list can have thousands of items).
this is the recomended aproach, retained fragments were designed to maintain data not UI elements, also nested fragments have some limitations. There are SO's on how to maintain list scroll position, ie.: Maintain/Save/Restore scroll position when returning to a ListView. So you should be able to find a working solution.
If you have some heavy data structure for your list, you can put it inside non nested retained fragment with no UI. This fragment will not be destroyed during config changes (like screen rotation), but it will still be destroyed when you close your app and Android decides to kill your process. So This may cause crashes if you forgot about this case, you must prepare your app for it.
Other option would be to store you list data in sqlite database, it would be immune to config changes, but probably updates of sqlite might be slow.

Advance ListView next item / setSelectionFromTop not working / Inhibit user scrolling ListView

Good afternoon,
I have a list view that show a list of items...well not all of them but they are all there. Rather than let the user scroll up / down the requirement asks for and up / down buttons. I have everything handled quite well EXCEPT how to advance the ListView. Say I'm looking at item 3 in the list. The user hits next...I want to ListView to advance to item 4. I am keeping track internally of which page they are on for incrementing / decrementing. I was expecting to find something like this but no dice.
ListView.MoveNext();
or
ListView.Move(int);
Per Brayden's suggestion I tried the accepted solution here: Maintain/Save/Restore scroll position when returning to a ListView and it did not APPEAR to scroll the list....i.e. it stayed on the first list item. I also tried setSelection.
Here is my code:
public void btn_NextClick(View vw_Current)
{
//increment page count 1
i_PageTracker ++;
//advance to next record
//int x = lstvw_LiftData.getFirstVisiblePosition();
View v = lstvw_LiftData.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
lstvw_LiftData.setSelectionFromTop(i_PageTracker, top);
//lstvw_LiftData.setSelection(i_PageTracker);
}
Based upon Vladimir's success and my lack thereof I wanted to provide some additional info that I thought irrelevant but....
I've extended the SimpleAedapter and override the getView. I also have a DataBinder to populate TextViews with certain data from the data object.
Interestingly when I set a breakpoint in the getView of the DataAdapter and the setViewValue of the binder at load we hit them as appropriate. However when the next button is clicked we do not hit them which I would expect if the list was advancing to the next position....hmmmm I wonder....I have another Idea....be right back.
I figured it out....but I don't know what to do about it. See not knowing what I am doing I shot myself. I ONLY want to see one item in the list at a time and I don't want the user to be able to scroll. Well what I did to accomplish that was to override getCount in the DataAdapter and return a 1. This SEEMED to be the answer as only one item displayed cool! But then overriding getCount also means there is only one item to display so we never advance...there's nothing to advance to.
So what I want to know is this. How do I keep the user from being able to scroll and force them to use the navigation button. Do I handle the scroll event and return null?
I figured it out....but I don't know what to do about it. See not knowing what I am doing I shot myself. I ONLY want to see one item in the list at a time and I don't want the user to be able to scroll. Well what I did to accomplish that was to override getCount in the DataAdapter and return a 1. This SEEMED to be the answer as only one item displayed cool! But then overriding getCount also means there is only one item to display so we never advance...there's nothing to advance to.
So what I want to know is this. How do I keep the user from being able to scroll and force them to use the navigation button. Do I handle the scroll event and return null?

ListView "onPopulate" Listener?

I want to set an initial scrolled position to a ListView.
I thought I could do that by calling list.setSelectionFromTop after adapter.notifyDataSetInvalidated, but of course the later only notifies the listview and the actual population may happen later.
Is there a way be notified when the listview has populated itself, so I can change the scroll?
Ok, so I tried onFinishInflate and onSizeChanged, but they didn't work. The later worked if the number if items changed, but not if the data was simply altered.
I then tried everything else, and the working methods to override were onFinishInflate and onSizeChanged. These are however also called on scrolling.
In fact, the last line in ListViews layoutChildren is a call to invokeOnItemScrollListener, so it turns out you don't have to extend ListView, but can simply set an onScrollListener.
No matter what solution you choose, you do however need to manually work around the problem of methods being called on scroll.

Categories