I have a sole activity for a lot of fragments.
In one of the fragments, I must now have a few tabs inside. The ways I can think of doing it is are:
Solution 1 - Creating a new activity just for that, and then implementing ViewPager :
My main concern regarding that solution is this:
So far, on my Activity , I had the following flow :
fragment 1 -> fragment 2 -> fragment -> 3 -> fragment 4 -> and on and on...
Now, suppose I have to implement those Tabs in fragment 3.
from fragment 2, I start a new activity placing a viewpager (with fragment 3 in one of the tabs and other ones in the other tabs). Then I need to be able to show fragment 4 . But since all the fragments in the app are placed on the original activity, it would mix up the flow or even worse. In other words cause either:
It would simply not show fragment 4 and so forth, because the running activity would be the one that is holding the tabs screen, while all the fragments are placed on the original activity, which would in the stack.
Not being able to go back from fragment 4 to the screen with the tabs, and then from 'back' from the tabs screen to fragment 2 , and then 1.
Solution 2 - Activity for result (with view pager):
The activity created for tabs screen could be an activity that results back to the original activity. so the flow would be like this:
fragment 2 -> new activity for result -> send result back to original activity stating that it needs to fire up fragment 4 now -> original activity opens fragment 4.
However, in that case if I go backwards from fragment 4, it would throw me back to fragment 2 instead of that tabs screen(3).
Solution 3 - Tab Layout :
Seems as the best solution.
However, to use that I need getChildFragmentManager() , which requires api 17 and above. My api is 16.
Now, if I use getSupportChildFragmentManager() I would have to use fragment v4. The problem with that is that all my fragments are native, and I can't just change that fragment 3 to be v4, cause then the previous ones and the following ones would have to be v4 as well. Changing all the fragments is not an option since I have about 50 fragments.
Another issue with solution 3
I've encountered , is that it crashes and prints : Error inflating class android.support.design.widget.TabLayout
I tried creating a new folder named values-v21, and created there a styles.xml for the tab layout, but that didn't help for some reason.
I hope I made it clear.
You have another solution derived from solution 3. This is to keep your current navigation(fragment1->fragment2->etc) and build a fragment to hold the ViewPager with simple layouts instead of nested fragments. This way you'll avoid: navigation issues, the problematic nested apis not being present on version 16(which you plan to support) and you'll also avoid a refactoring to use the support fragment api.
And if at a later time you drop support for version 16 you could refactor each of those simple layouts in a nested fragment and use the native getChildFragmentmanager().
Related
I set up my application in the following way and am curious if it's considered "best practice." I have two activities and two fragments. Activity 1 launches and immediately uses Fragment 1 to display a RecyclerView of items. An Item is clicked in the Fragment, it's communicated back to the Activity through an interface, some logic occurs and Activity 2 is launched, which immediately uses Fragment 2 to display the detail of the selected item.
I did this because A)I like the logical flow of Activities within an application and 2) I needed to create tablet layouts in which I could use both the Fragments to fill the screen.
The more I'm looking at this thing, I'm thinking why not simply have 1 Activity that manages both of these Fragments? Activity 1 launches Fragment 1, item is clicked, info goes back to Activity, FragmentManager replaces Fragment 1 with Fragment 2.
My question does one of these ways adhere more to "best practices" or are they both fine and it's a matter of choice?
You've not described your problem clear enough to use more than one Activity, other than unrelated data to the list and what happens when you click there.
What you described is a "master-detail" flow, and that is a good use case for one Activity and two (or more) Fragments - a list + some detail page. This especially makes sense on larger screens when you can show those Fragments side-by-side.
For example, you can have an Activity that holds a navigation screen (whether that be tabs, a drawer, or a bottom view), then everything you navigate to within there is a Fragment.
Otherwise, you redirect to some "settings" page, for example, that is a new Activity, which demonstrates the "Single responsibility principle" in your UI.
Well you can go with the single activity - multiple fragments. You can pass data between fragments using bundle as well. Matter of choice also depends on the use case. But fragments are made to use as light weight activity that requires less resources then activity. Most of the things are possible with fragments. So unless it is not required to use activity my choice goes with single activity - multiple fragments.
I used to have 3 activities with 3 layouts.
1. HomeActivity.java (activity_home.xml)
2. HelpActivity.java (activity_help.xml)
3. SettingsActivity.java (activity_settings.xml)
Whenever i had to open other activities, i used animated slide-in-out intents using overridePendingIntent. In this way, all the variables of HomeActivity stayed in itself and HelpActivity's variables/methods were in itself and same for SettingsActivity. I used onCreate() in these to perform some activity specific code. and, android:onClick="fetchSarcasm" from activity_home.xml was calling specified method in HomeActivity.java. So, there were no conflicts. All the normal things, that happen in an AndroidProject with 3 activities and used intents to switch to one another, were happening as i wanted.
But now, I wanted to migrate to ViewPager instead of slide-in-out intent transitions. In this way, there will be only one Activity with an XML of ViewPager. This ViewPager and its FragmentPagerAdapter gets the Pages from 3 classes extending Fragment with relative XML layouts.
I want to ask: Where do i write my Page Specific Code for onCreate(), layoutView's onClick="" and for onChangeListeners. Because, 3 classes extending Fragment do not have any Context or findViewById() and they do not respond to android:onClick="method" in different layouts.
Do i need to mix all that code of three activities into one containing ViewPager? If so, this makes ViewPager activity pretty heavy. and, writing if(page=2){ dothis(); } seems absurd for all pages at every code point. Any checkbox(view) that is in page 3, becomes null in other pages.
I know this might be a stupid question. I have spent almost 4 days trying to achieve something but i can't. Also, this is just my 2nd month in android, so i am new. I do not use Action Bars, Tabbed Bars or Navigation Drawers.
I am available on SO Chat too if you want to ask something more.
I just want to know how do i merge all the work i did when I was not using ViewPager.
If you're only reading the Preferences once for each Fragment, you can move your previous Activity.onCreate() logic to each Fragments onViewCreated() or onCreateView(). Read your shared Preferences there and set your Checkboxes accordingly.
Fragments inside a ViewPager aren't necessarily recreated on each page change. You can change how many Fragments are instantiated at a time with ViewPager.setOffscreenPageLimit(int).
Fragment Lifecycles explained
I want to use multiple fragments in each tab of Tab Host.
I am googling for last 5 days but nothing is working in my case. I got a good working solution
Seperate Back Stack and Sample Project Here .This maintain a separate Custom Back Stack for each tab having lots of fragments and store Fragment object in Custom Stack. But when ever I want to re-add any fragment that I already created and stored in its custom stack(as an object), all it's life cycle methods are called once again as are called first time. This is the problem. In this case all the views of fragment layout are recreated and it behaves like a new fragment.
I want to implement functionality like tabs having activity group(in which lots of activities are combined in a single tab using activity group) with the help of fragments.
Please help me in solving this issue........
My App (minimum API 14) uses an ActionBar with 3 tabs.
The tabs are:
i. enter data (approx 10 fragments)
ii. manage data (15 fragments)
iii. view data (8 fragments).
Each tab has a default fragment, but then has multiple fragments depending on user choices.
I would like the user to be able to swipe between the 3 tabs (by swiping the content) hence I need to use ViewPager and the compatibility library v4.
The advice I have picked up (after much research) is to use a MainActivity which hosts the ActionBar and tabs with fragments for the tab contents. But I'm worried about the number of fragments. Also some of the fragments need to use date and time pickers which means DialogFragments coming out of fragments. It's starting to get very complicated.
Does anyone see any problem with my using Activities instead of fragments for the tab contents?
Fragments act on the UI side just like activities except you can combine multiple together. So you don't need to create a different fragment based on user choices, you just need to change the fragment just like how you would change an activity dynamically.
Also if you want to use ViewPager, you are basically forced into using fragments.
The nice thing about fragments is that they are reusable, so most likely you only need a few fragments and then you can combine them in different ways for the different use cases. This also makes your tablet UI a lot easier to create.
For reference: http://developer.android.com/guide/components/fragments.html
I'm having a bit of trouble implementing a design based around multiple ViewPagers.
At a high level, I have a FragmentActivity with just a FrameLayout as it's content. I have 3 different Fragments that I want to display. All 3 are full screen and only 1 will be used at a time.
Fragment 1 is a basic fragment with some TextViews and ImageViews.
Fragment 2 has a ViewPager and a FragmentPagerAdapter that feeds it several simple fragments.
Fragment 3 has a ViewPager and a FragmentPagerAdapter that feeds it several simple fragments (that are different from Fragment 2)
In my FragmentActivity onCreate() I get the FragmentManager and begin a transaction to replace whatever is in my FrameLayout with a new instance of Fragment 2.
At this point everything is working as expected. My ViewPager in Fragment 2 works perfectly.
Now I have a menu option that replaces the Fragment 2 in my FrameLayout with a new instance of Fragment 3. This also works fine.
The problem arises when I try to put Fragment 2 back into the FrameLayout with another replace transaction. I see my PagerIndicater at the top, but my pages are blank.
I've tried just creating a new instance of my Fragment 2 and calling a replace transaction. I've also tried setting a tag on my Fragments when I call replace and adding a findFragmentByTag check before my replace instead of creating a new instance. Both gave me the same result of blank pages after my second replace.
For reference
My first design was simply a FragmentActivity with a ViewPager and a ViewIndicater. I only had Fragment 2 and Fragment 3 from my description above and a menu option to switch between them. To switch I had 2 different FragmentPagerAdapters defined and just called ViewPager.setAdapter to set the selected FragmentPagerAdapter. This was working perfectly, but now I need a new top level Fragment that isn't using ViewPager at all. This is why I decided to move my ViewPagers out into their own Fragments. My idea being that I would just swap in my fragments to a FrameLayout.
I don't have my code in front of me right now so I can't post any, but I'll add some code to my question tomorrow to help facilitate answers.
This question is a possible duplicate of Navigating back to FragmentPagerAdapter -> fragments are empty.
If your app can handle it (API 17), use getChildFragmentManager(). This problem seems to occur when using a Fragment to host your ViewPager and using FragmentPagerAdapter. Changing to FragmentStatePagerAdapter seemed to fix the problem as well, but I still think using getChildFragmentManager() is the smartest thing to do.
brockoli you can used not "good way". But for my it's worked.
You can use in view 2 layouts, where you bind fragments. First - for fragment with fragments. Second - for other fragments.
On replace fragment with fragments do not replace, but only change visibility first layout to gone and add new fragment to second layout. On back, remove fragment from second layout and set visibility for first layout to visible.