Destroy Pages on ViewPager and FragmentStatePagerAdapter - android

We are trying to create an Android application that is based on ViewPager that receive during runtime instructions to add and remove pages. Almost like a tabbed browser experience, that you can remove the current tab, or remove a specific tab.
Following Google documentation we use FragmentStatePagerAdapter, that is intended to be used in situations when there are a large number of pages, working more like a list view.
But when we try to:
- Remove a page that is not on the screen
- and create a new fragment object from the same class
- and on the same position of the page removed
We noticed that the Android platform recover the dead page and display that to the user. The new object that we just created simply does not run “onCreate”, “onCreateView” or “onActivityCreated”.
We are looking to ways to fix this issue forcing the platform to use our new fragment object from the same class. Any ideas?
We found out that if we destroy the current page the platform indeed destroyed the page and created a new object from the same class. Here is a small example replicating the problem and this behavior.
Source: http://dl.dropbox.com/u/8333012/SimpleAdapter/SimplePager.zip
Video: http://www.youtube.com/watch?v=-oaXXwU8PSI&hd=1
From this project when you touch the TextView on the first page it was designed to remove the second page (which is green) to a new blue page. You will see that even doing that from the first page the second page remains green. But when you press the back Android button on the second page (green) and touch the TextView the second page created will be the right blue color.

When you are dealing with ListView's and change the underlying data of your adapter you call notifyDataSetChanged() and any View reflecting the data set will refresh itself. Thats the way you should go with fragment pager adapter too.
In your case you do not notify the adapter. However, in case of FragmentPagerAdapter/FragmentStatePagerAdapter it does not make a difference because those adapters ignore notifyDataSetChanged() "by default". To make it work override the getItemPosition() in your adapter implementation
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
And as already said, after you add/remove fragments call (in your showOtherPage())
mAdapter.notifyDataSetChanged();

Related

How to go directly to a specific fragment using ViewPager2

I am trying to create an app using Viewpager2 that allows scrolling between fragments similar to below image but WITHOUT the tablayout at the top.
So if you scroll left and right you would swtich between the fragments. Thats fine and dandy.
However my final app would have more than 5 tabs so i dont want the tab layout listed on top. Instead I would have a menu option that would let user choose which fragment to view.
I cannot figure out how to get the viewpager to go to a specific fragment directly (eg. from 2nd fragment to the 5th fragment), and when navigating between fragments I do not want a fragment to start from scratch if if was created already.
I am using FragmentStateAdapter with my ViewPager2. Should i be using another adapter for this? Any ideas woule be greatful.
The easiest way to implement this feature is to define your ViewPager as static in your activity (so you can access it from anywhere in your application, including fragments). You can make it public, or you can make it private and create a getter for it.
private static ViewPager mViewPager; // This is the global variable
public static ViewPager getViewPager() { return mViewpager; } // This is the getter
Now lets say we have an activity MainActivity which contains the ViewPager. Each fragment inside this ViewPager contains a button which should control the page (doesn't have to be in the ViewPager, could be anywhere as long as it has a reference to your Activity and that Activity is still running, so don't start another one).
ViewPager contains the method
setCurrentItem(int item, boolean smoothScroll)
(smoothScroll is optional and is just for animation purposes)
Now you can do:
MainActivity.getViewPager().setCurrentItem(itemNr);
Or if you want a fancy scroll animation:
MainActivity.getViewPager().setCurrentItem(itemNr, true);
Now your second question / issue was that you mentioned you don't want fragments to get recreated. In that case I think it is better to use FragmentPagerAdapter, which maintains your fragments. You can call the following method to set a limit to these pages:
mViewPager.setOffscreenPageLimit(LauncherViewPageAdapter.NUMBER_OF_PAGES); //NUMBER_OF_PAGES was just a static constant in my LauncherViewPageAdapter class which extended ViewPageAdapter.
Note: Default this limit is 3, but you really don't have to worry about performance. I implemented 4 pages / fragments (widgets, tiles, app list, application settings) without any memory issues (even on older devices). Just don't put them full with bitmaps / heavy memory usage stuff.
I'm currently working on a launcher application which also uses ViewPager, so feel free to reply with a question about the ViewPager, since I solved the basic issues I had.
You can make use of setCurrentItem method of your ViewPager2. Just pass the index your wish to navigate to starting from 0. As for not wanting the fragments to start from scratch simply use setOffscreenPageLimit method of viewpager2 and set it to like 4 in case you have 5 pages so that all 5 pages stay in memory. It actually defeats the purpose of FragmentStateAdapter and ViewPager2 though.

Load ListView inside TabHost's tab smoothly

I am trying to load a listview which gets data from a server inside a Tabhost's Tab. But everytime i switch to another tab and come back there is always a delay generating the ListView. Once the ListView is generated everything runs smoothly, bubt i would love to load the listview smoothly as well with no visible delay.
I have a method that i created, called loadStatuses(), which is called in the following places.
OnCreate and OnResumed.
private void loadStatuses() {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
adapter = new MyCustomAdapter(getActivity().getApplicationContext());
adapter.setImageKey("Status");
mListView.setAdapter(adapter);
}
});
}
As you can see i am basically just re-creating the listview, is there away to make this much more smoother with no delay, good on memory and performance?
you do not need to call your loadStatuses at onRsumed(). just calling it at onCreate is sufficient.
I am trying to load a listview which gets data from a server inside a
Tabhost's Tab. But everytime i switch to another tab and come back
there is always a delay generating the ListView. Once the ListView is
generated everything runs smoothly, bubt i would love to load the
listview smoothly as well with no visible delay.
In order to achieve that you can use FragmentStatePageAdapter and setOffscreenPageLimit(Number of tabs); to not loading your content again. you can also use caches to prevent from downloading again and again when user switch the tabs.
Hi, the reason i am doing it this way is because instead of Using
setNavigationMode(ActionBar.NAVIGATION_MODE_TABS) i am using the
navigation drawer, and using the tabhost to be able to use both the
navigation drawer AND tabs.
For this reason i am using
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD)
instead and inside the MainActivity, which in this case is "Home" in
the navigation drawer i have the TabHost.
Can i do this without using the actionbar?
Yes, you can use PagerSlidingTabStrip library. I answered step by step how to run it with:
PagerSlidingTabStrip implement guide
Also note ActionBar.Tab is Deprecated since API level 21
I think you should use Swipable Tab view because It is a standard way . You can follow following url :
http://developer.android.com/training/implementing-navigation/lateral.html
http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/
and load data from server in data model and then send it to adapter , so it will not load repeated when changing the tab.
Once load you can use without interruption.
If you need any further help, plz let me know.

Android veiwpager with fragments view flow issues

Im relatively new to android so im trying my hand at what i though would be an easy-ish app but I've ran into an issue to do with view/activity flow that i cant get an understanding on.
i have a fragmentActivity that uses a Viewpager to create tabs, each of those tabs is its own fragment class, thats all fine and working, but now i need to have one of the tabs display a list, when selected it takes you to another "view", my problem is how to create the first list and then how to handle tha clicking of an item in that list to take you to the new view so that the tabs stay in place and the back button doesn't exit the app.
currently ive swapped out the fragment with a list fragment that uses an arrayAdapter to build itself, this has worked as far as the list goes but i cant for the life of me figure out how to utelise its onclick() method to move on the the next screen, without as i said losing the tabs or having the back button simply exit.
so im not sure if A, the list fragment is the way to go, or B if it is how to move on to a new screen correctly
i can post code if needed but its a very general implementation of the classes mentioned so im not sure code will help
The callback you want to handle a click on an item in the list is onListItemClick.
As far as presenting a new screen, you can use a FragmentTransaction to replace your fragment with a new one, which gets a little hairy if you're doing this inside of a ViewPager. The code would look something like this:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.some_containging_view, new SomeFragment())
.addToBackStack(null).commit();
Otherwise, you could simply launch a new Activity, which is simpler, but will mean that the tabs won't be present on the new screen unless you duplicate them there.
An elegant solution was finally found here, it uses a wrapper fragment around my list fragment so the pager is just concerned with the wrapper, meanwhile within the wrapper i can perform fragment transactions to my hearts desire, one small note the linked code uses getChildFragmentManager() that needs to be changed to regular fragmentmanager() from support.app for the backstack stuff to work.

Android: ViewPager, intercept on fragment load

I have a ViewPager which usually preloads some of its elements.
The user can interact with one page which should affects a part of all other elements of the ViewPager.
Currently all my logic is in onCreateView(). I need to get a handle when element is actually shown and change the common part.
I tried with onResume() but this function is called earlier. I don't want to redraw the whole element because this is not effective.
I am not sure but try using this method:
viewPager.setOffscreenPageLimit(0);
This method will call only one fragment at a time, while you are on that fragment.
Or
Another way is that you can get position of view pager's fragment at run time which is front of screen and according to that particular fragment position you can simply call your method by checking position Like: if(position == 1){}.

Recreate Fragment of - View Pager - FragmentPagerAdapter

In my application I am using ViewPager from the support library- v4
In main screen I have viewPager which got max 5 Fragment, all fragment belongs to one class ArticlePager
Now in main screen there are list on categories, now the content of the pager is based on that selection,
The problem I am having is, I have used FragmentPagerAdapterwhich stores the Fragment and if the fragment is already exist, It will return the old Fragment without recreating it. That things runs perfectly, but Problem Occurs # the time of orientation change.
For instance
If there are 5 View normally in every fragment For the given position, but There are also some which contains 2-3 views. Now if I change the orientation on page No. lets say 5 which contains only 3 view inside.
So, by now in every category on Page 5 I'll got the view containing 3 view, which is not something I want.
In my application each category contains the pagination
Is there any way such that i can destroy and recreate the Fragment on click of category? or any other work around
Thank you
OK thanks to open source I find my solution, FragmentPagerAdapter I have override the method instantiateItem and got the solution.
This can be easily achieved by FragmentStatePagerAdapter such that it doesn't store the fragment. It recreate it all the time, but I don't want that in 100's of page because of only few pages.
So if I understand correctly, your problem is that after rotation, the wrong set of fragments are in you ViewPager?
Why don't you check the current selected tab in onResume() or onStart() of your Activity, and create/assign a new PagerAdapter for you ViewPager with the correct fragments?

Categories

Resources