Android ViewPager with all fragments of same class without transaction - android

I know this question has been asked many times before but I couldn't find an explanatory answer.
I want to have a single MyFragment.java and display it for all 3 pages of ViewPager.
But when I try to create a fragment with this method:
new MyFragment()
and add it to the ViewPager I get this error:
java.lang.IllegalStateException: Fragment already added
at androidx.fragment.app.Fragment.setInitialSavedState(Fragment.java:679)
at androidx.viewpager2.adapter.FragmentStateAdapter.ensureFragment(FragmentStateAdapter.java:269)
at androidx.viewpager2.adapter.FragmentStateAdapter.onBindViewHolder(FragmentStateAdapter.java:175)
at androidx.viewpager2.adapter.FragmentStateAdapter.onBindViewHolder(FragmentStateAdapter.java:67)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
I'd like to know if there is any possibility to add the same fragment to ViewPager.
Possible applications of it include
A web browser having WebView fragments in Viewpager
Why exactly do we need to use singleton fragment?
Why can't we treat fragments as recycler items which can be multiple instantiated?
Even the viewpager2 is becoming more like RecyclerView.
If it is impossible to instantiate fragments repeatedly and add them
to the same ViewPager then are there any other ways except replacing
fragments in ViewPager adapter with normal inflated views? Would that
be a tolerable solution?

You get this error because when you add the fragment you don't put a distinct tag on it, so it checks whether the fragment is already added by its class. And the viewpager stores some pages in memory, so the previous fragment even though is no longer in view, is still in the memory.
When you add the fragment, give it a distinct tag

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.

Android: Viewpager with multiple fragments of the same class with fragment transaction

There are already some open threads about this subject but mine is a little different and I can't seem to find out how to do it. This is my problem:
I'm creating a listview (recyclerview) inside a fragment which I put inside my Viewpager. This listview represent a timeline/agenda of the current day. Whenever the user swipe left or right, the exact same listview fragment needs to pop up with different data (data from the day before or after). Whenever you click on one of the items in the listview, the fragment is replaced by a detailed fragment.
This doesn't sounds so hard but here comes the tricky part:
All the examples I see on the internet show different Fragment classes inside the Viewpager which makes it possible to do a transaction from the listfragment to the detailed fragment, and all the examples that use multiple fragments of the same class don't do a transaction to a detailed fragment.
Whenever I'm trying to do the transaction to the detailed fragment, it looks like it can't find the proper fragment container (since there are 3 of the same now). I'm pretty sure of it since the new fragment does appear but the old fragment stays visibile underneath (when I don't use the viewpager it works fine).
If anyone could provide me with a simple example of a viewpager with multiple fragments of the same class that have a transaction to a detailed fragment you would save my day.
Regards

Keeping PageView Fragment's View from disposal

I have an Android Application implementing a PageView with Tabs found here: https://github.com/sbpc/ajavacc The PageView loads its Fragments and displays everything properly; but occasionally the individual Fragments become disposed. Is there a way to either store the Fragment's state, prevent the pages from being disposed; or do I need to save the values which construct each page to a file?
The class MainPagerAdapter is already using FragmentPagerAdapter which keeps the created Fragments in memory. You can go one step further and add the method setRetainInstance(true) to each Fragment in the ViewPager. This should work. You can read more about this here.

Android: Different fragment for each ViewPager

In Android, when creating Action Bar Tabs with ViewPager, what's a way of giving different fragment for each ViewPager? Let's say I want the first tab to be login form, the second a signup, in fragment_login.xml and fragment_signup.xml files respectively.
Where/how do I initialize these fragments and show as appropriate tabs are selected? I would prefer to do this all in one Fragment class, instead of creating individually for each one.
If you are using a small number of fragments then you can implement FragmentPagerAdapter. For showing larger number of fragments FragmentStatePagerAdapter is recommended. You can keep all the fragments in one class(Activity class) and make each fragment a subclass of that class but I think having different classes in respective .java files would make your code more elegant.
Initializing the fragment is generally done during fragmentTransaction and appropriate data are passed via Bundle.

A bug in ViewPager using it with other fragment

I need your help.
I have one Activity with two fragments: one fragment with simple TextView in LinearLayout and other fragment: ViewPager with 3 fragments in FragmentPagerAdapter.
I make transaction with replace action, but I have error from ViewPager: java.lang.IllegalStateException: Recursive entry to executePendingTransactions.
That's a source code that show this problem, maybe anybody knows how to fix it.
Um no. A ViewPager extends ViewGroup. How does that make it a Fragment?
Yes, you're right that nesting Fragments isn't supported. However, it works if you have a Fragment holding a ViewPager whose Adapter contains several Fragments. Trust me, it works. I'm using it in the current project I'm working on right now and I've even got nested ViewPagers without the horizontal touch events fighting for control, so essentially I have Fragments within a Fragment.
With revision 11 of the Android Support Library, you can now nest fragments within fragments to avoid the recursive exception. See this question How to add a Fragment inside a ViewPager using Nested Fragment (Android 4.2)
A ViewPager is basically a Fragment, and you can't put Fragments in Fragments. Period.

Categories

Resources