I'm writing an app for phones and tablets. Like the Contacts app, there are multiple tabs (2 in my case). For the phone UI, they're managed by a ViewPager, with a fragment for each tab.
But for the tablet UI, each tab is an activity, rather than a fragment. They have to be, because you can't put fragments inside fragments. (Right?)
I realize I could just call setContentView() on the tab listener, but wouldn't that destroy the activity every time it was changed? I'm confused by a lot of this.
What's the best way to do this without breaking my phone UI?
A well designed tabbed UI never uses Activities for tab content.
You're correct in that you cannot nest Fragments in the current implementation, but that doesn't mean your only alternative is Activities. Tabs should always act as a view switch; a tab switch never creates navigation history and tab navigation should always happen within the same Activity.
Remember that Activities and Fragments are just controllers from an MVC point of view. They exist to respond to lifecycle events and manage elements of your application in response to those events, including views within your UI. The content of your UI is wholly determined by the view hierarchy of the current window and you can manipulate the view hierarchy in whatever way makes sense for your app. (While preferably still following the design guidelines!)
Since Fragments have a built-in mechanism for managing a view sub-hierarchy they're often a natural choice for factoring your UI but they're not the only way. ViewPager PagerAdapters can manipulate view sub-hierarchies by inflating them from the resource system, recycling views the way a ListView does, or any other mechanism you can come up with and not use Fragments at all if the lifecycle events they provide aren't needed. Different layout resources may include or exclude certain elements based on screen size using different layout variants for different resource qualifiers.
In short, don't get stuck on the idea that Fragments are the only way to do multi-pane UIs, or the only way to implement each page of a ViewPager. They're powerful options for both, but depending on the information architecture of your Activity you may find yourself using them in a different way than another app and that's OK.
Overall, if you're having trouble determining where the logical cut points are when factoring your Activity's UI, you may be building an overall UI for your app that is going to be as awkward to use as it is to implement. Let the UI design guide your implementation. If each tab is naturally switching out the entire content of the Activity window, then each tab might be well suited to a Fragment. Perhaps those Fragments in tablet mode expand their capabilities and present more than one pane in their respective layouts using different layout resources.
Related
I am new to developing on android, finding myself somewhat confused regarding fragments and activities, and when to use the former specifically.
I want to achieve the following:
Have an activity with buttons for displaying different graphs. The selected graph should appear on screen in a panel overlaying the screen, or in fullscreen, and it should have functionality/buttons e.g. for selecting a graph timeframe.
Would creating each graph-page as fragments, routing events to the main activity be a good idea here, or should I just make a new activity for each? Or are there better options?
Cheers
I wouldn't recommend to use separate activities for this task.
The fragments are a great option for your case. You can save the state of each fragment and thus avoid recreating the graph views every time (which saves lots of CPU time if amount of data is big).
Read info about FragmentTransaciton and of course learn about working with Fragments in general. Maybe you should also try using ViewPager if you want to avoid switching fragments by yourself.
In case of using ViewPager you should use FragmentPagerAdapter (this one saves fragments for you) and you will just switch between them from your MainActivity. In each of the fragments you will implement your own graph with its own (or shared) layout file.
This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible.
im developing an application with multiple screens using activities and fragments. The principle behind my decisions to use one or the other are based on the interaction in the application.
I have come to the conclusion that you should use an activity whenever major UI elements remain present after an event has occurred that forces the views inside the UI to change (An example of this can be a tabhost nested in the toolbar styled as the Google Play store android App with multiple fragments as childs. Another example is fragments representing the different rows or clickable elements on a navigation drawer).
So right now im presented with the dilemma of choosing once again between the two (fragment or activity) for a UI element that is going to be present across my whole application. Its triggered by a floating action button that launches a creation tool for an element inside my application and i needed to be accesible across all of my apps screens.
So to sum things up, what i need to know if its better to use a fragment or an activity for an element that is ever present across my whole application.
Thanks in advance
Use Fragments or a compound Views. But both in the right way.
Fragments are thought for reusable combinations of views. Compound Views are Layouts containing views. They are the right way if you want to create views from more primitive views, for example a View containing TextView and a increment- and decrement-button.
Fragments are more Activity-like. They have a real lifecycle. Your description looks like you want to create acitivity-parts. And thats exactly what fragments do.
A Fragment represents a behavior or a portion of user interface in an
Activity. You can combine multiple fragments in a single activity to
build a multi-pane UI and reuse a fragment in multiple activities.
Taken from Android SDK Documentation: Fragments.
I am trying to create a layout in an activity that will look different in landscape and portrait, however it will contain the same sections, just in different places on the screen.
Most examples I find on fragments is always the list and detail, which is not what I'm looking at.
In my example I have, amongst others,
a scrolling image section (carousel)
a page title with some brief details
a carousel of thumbnails
two buttons
full details of the page
Now in the landscape layout, the image section will always be on the left side with down the right side, the page title, carousel of thumbs, two buttons and full details.
In the Portrait the title will appear at top, with image carousel beneath, then thumbs, then buttons etc.
The way it works in my head, is that each section should be a fragment, and then depending on the layout file in the respective res/layout folder corresponding to land/port, the fragments are arranged accordingly. But I'm also thinking is each section a whole fragment? Or could it be a separate view that get's loaded in, but just in a different order depending on the screen orientation.
I hope that made sense?
Does anyone have any good tutorials that explain exactly when you should and shouldn't use fragments. All the usual suspects just list the list/detail example, which is not applicable in my case.
tl;dr Can I use fragments as modules/blocks in various layouts or should I just create other layouts and display them inside the main layouts.
Fragments can be used to have split screen and to store previous state unlike views. It is difficult to manage back button with views
If you just want to change how the screen is laid out, the answer is neither. You can define orientation-specific resources (either a separate layout file for each orientation or different dimensions/constraints for each orientation) and the system will just provide you with the correct resource set for the current orientation.
That said, it sounds like you may be describing a modified version of master/detail flow. If this is the case, fragments are a good way to go since the landscape view is actually several separate screens in the portrait version of the app, so each section needs it's own state and lifecycle, which fragments provide.
Now, I know you said you wanted an example beyond a list and detail view, so here's some more details on when to use fragments:
Fragment, like activities, have state and lifecycle. Custom views do not have lifecycle and are completely dependent on the activity or fragment containing them.
You might use a custom view when you have a widget on screen that is used in multiple places and is just like any other view – bound to the activity when the layout is inflated and controlled from there. It's a way to either reduce duplicating combinations of views in your layout or to draw a custom view that doesn't exist yet.
Fragments are good when you need some state or lifecycle for a section of the app that might get used in multiple places or shouldn't be logically connected to the activity it is contained in. If you use the new Navigation Component, you actually just define one activity and then each screen in the navigation tree is a fragment that gets swapped out as the user navigates around the app. Here each child component on the screen (each "screen" that the user navigates to) has it's own lifecycle, business logic, etc, so mixing the code for all of that in the activity wouldn't make sense.
So the question comes down to what you are trying to build, and this may be a case where the best way to learn the difference is to try each option out as bit. The differences become more clear with practice using them. As a general rule of thumb, personally, I only really use custom views when I am trying to make a new view that doesn't exist elsewhere. If what I'm trying to do is simply a matter of laying out existing views in a new way, the answer is probably some trick in the layout file or layout code inside the activity. If I'm trying to make a stand-alone piece of the app that does stuff, especially if it also appears in multiple places in the app, I'll probably be building a fragment.
We recently converted an app from a multiple activity based one, to one with a single activity with multiple fragments. The activities that became Fragments used to contain fragments themselves, so we use child fragment managers to host the Fragments in the Fragments (these child fragments I should add, are small and there can be 4 or 5 these on the screen at one time).
This has caused a few issues, namely having to create, and keep track of Unique IDs for the Fragment holders. (Which cause headaches when dealing with the Backstack as well as if any are in any sort of AdapterViews).
We're thinking of just rewriting these components to extend some sort of ViewGroup, likely FrameLayout or LinearLayout. We already do that anyway in some cases, but I was wondering if there are any disadvantages to doing it that way? (I must admit, I don't really see the big deal about Fragments... anything you can do with Fragments, you can do by creating a Custom View. Is this wrong?).
This is a bit of a reverse answer, explaining fragment use. In general you can do most things with Activities, but as the SDK supports fragments, many things will become more cumbersome (ViewPager is an example where fragment use is great).
The advantages (of fragments): code encapsulation, reusable chunks of UI.
The disadvantages (of fragments): more code (e.g. FragmentManager, FragmentTransaction).
Your original use of activities was good, it's not a case where I would have switched to fragments.
Let's say I designed a mobile phone app with two activities: ContactList and ContactDetails. So far so good, no reason to use fragments yet. If I wanted to support a larger device, it would behoove me to display both screens side by side. This is where fragments come in handy. In terms of exactly how to structure your activities/fragments, there's some good advice here:
https://developer.android.com/guide/practices/tablets-and-handsets.html#Fragments
Here are the important bits:
Multiple fragments, one activity:
Use one activity regardless of the
device size, but decide at runtime whether to combine fragments in the
layout (to create a multiple-pane design) or swap fragments (to create
a single-pane design).
Or...
Multiple fragments, multiple activities:
On a tablet, place multiple fragments in one activity; on a handset,
use separate activities to host each fragment. For example, when the
tablet design uses two fragments in an activity, use the same activity
for handsets, but supply an alternative layout that includes just the
first fragment. When running on a handset and you need to switch
fragments (such as when the user selects an item), start another
activity that hosts the second fragment.
.
The approach you choose
depends on your design and personal preferences. The first option (one
activity; swapping fragments) requires that you determine the screen
size at runtime and dynamically add each fragment as
appropriate—rather than declare the fragments in your activity's XML
layout—because you cannot remove a fragment from an activity if it's
been declared in the XML layout. When using the first technique, you
might also need to update the action bar each time the fragments
change, depending on what actions or navigation modes are available
for each fragment. In some cases, these factors might not affect your
design, so using one activity and swapping fragments might work well
(especially if your tablet design requires that you add fragments
dynamically anyway). Other times, however, dynamically swapping
fragments for your handset design can make your code more complicated,
because you must manage all the fragment combinations in the
activity's code (rather than use alternative layout resources to
define fragment combinations) and manage the back stack of fragments
yourself (rather than allow the normal activity stack to handle
back-navigation).
This question already has answers here:
What is the benefit of using Fragments in Android, rather than Views?
(6 answers)
Closed 10 years ago.
What is the advantage to using Fragments over using custom Views that are reused in different layouts?
In the original blog post introducing fragments, Dianne Hackborn says that
[Fragments] make it easier for developers to write applications that can scale
across a variety of screen sizes, beyond the facilities already
available in the platform.
and she goes on to explain Fragments in the context of making a tablet layout for an app that combines the UI of two activities from the phone version of the same app.
But it seems that the same reuse could be achieved using custom Views. The main different between Fragments and Views seems to be that they have differing lifecycles...
The Fragment lifecycle is:
onAttach(), onCreate(), onCreateView(), onActivityCreated(), onStart(), onResume(), onPause(), onStop(), onDestroyView(), onDestroy(), onDetatch().
The View lifecycle is:
ctor, onFinishInflate(), onAttachedToWindow(), onMeasure(), onLayout(), onDetatchedFromWindow()
I'd like to hear from developers with experience writing large apps about what benefits (if any) they've seen in using Fragments vs custom Views to divide up the UI into reusable pieces.
The main reason is that fragments are more reusable than custom views.
Sometimes you can't create a fully encapsulated UI component relying on views alone. This is because there are things you would want to put into your view but can't because only an Activity can handle them, thus forcing tight coupling between an Activity and a View.
Here is one such example. Lets say you want to create a reusable UI component that, among many things, want to capture a photo and do something with it. Traditionally you would fire an intent that starts the camera and returns with the captured image.
Notice that your custom UI component can't fully encapsulate this functionality because it will have to rely on hosting Activity's startActivityForResult because views don't accept activity results (they can indirectly fire an intent through context).
Now if you wanted to reuse your custom UI component in different activities you would be repeating the code for Activity.startActivityForResult.
Fragment on the other hand cleanly solve this problem.
Similarly your fragment can contribute items to your options menu, something traditionally only an Activity could do. Again this could be important if the state of your custom view dictates what goes in the menu.
A fragment is way more than just a view. In fact it can even be totally without a view. It can have all sorts of stuff in it including AsyncTasks, various Listeners, file and database access and so on and so on.
Think of it as a small activity, but you can have multiple of them on the screen and work with them all including communicating with each other while they are visible.
E.g. you could have a list of shopping cart displayed in one fragment and the currently selected cart in detail in another fragment. You then e.g. change the quantity of an item in the detail view and the list view could be notified about it and update the total price in the list view. You can totally orchestrate interactions like that nicely while e.g. still having only one of them visible on a smaller screen device.
I have refactored a large business app (>15 activities) from activities to fragments to get good tablet support and I would never start a new app without fragments.
Update Feb 2016: While the above still holds true, there are complexities with fragments that caused many people to entirely avoid using them. Newer patterns such as usage of MVC approaches and more powerful views provide alternatives. As they say .. YMMV.
Some description:
Imagine Activity as a plate that hold one big cake.
Fragment would be a container that slices the same cake into pieces.
Each slice contains it own logics (listeners, etc).
And in total they are almost no different with the one big cake.
The benefit:
When you plate can't hold a big cake. (Screen is small) You can easily use a a few plates (Activity) to hold each of them WITHOUT the need to move your logics into the new activity.
Better re-usability. I have some instances where I could reuse a fragment entirely in another App. You might claim that a custom view could does that too. But refer to point 1, I could reuse it with just few lines of layout changes but for a custom view, it have to find a way to plug it into both layout and code.
It is, in some sense, a more OO ways of organising your UI logics in Android programming. When you have a feature (A new partition on the screen for example), you create a new Fragment class, with minor modification to existing activity class. However if you are programming only with activity, you will need to add logics and make big modification on tested class.
Just my 2 cents. :)
The lifecycle methods are probably your biggest hint. If you think about it, they correlate closely to the activity lifecycle (with some hooks into the activity and views). In fact, in the article you linked, Hackborn says:
In some ways you can think of a Fragment as a mini-Activity
As with many things in software design/development, there are a multitude of ways to do things. There are many different places you could put your code. Yes, you could probably put a lot into a view, but keeping different concerns separated in different classes is a good thing though. The classic pattern of this is MVC and it applies in this scenario. You don't want to bake in too much controller logic into your view. It's better to keep it in controller-like classes which are the activity and now the fragment. This is why the fragment's lifecycle is more like the activity's than the view's--it was made to facilitate this kind of organization.
I touched Fragments once and found them not very useful (see this post). From what I have read, A Fragment is really a fancy word for an Object with access to Activity Context. I like to ignore Fragments in my work, and just create these Objects myself. I have created very large, very demanding apps by passing an Activity to constructors, instead of Context. One major benefit, however, for using Fragments is that they are supported by the View layout system - so you can easily add them to Android xml (if you use it for your layouts).
Custom views are much more work than just using fragments in place of your activities. if you decide to use Activities and custom Views, you have to create your custom view, and then you have to implement the same activity lifecycle methods in your activity (a very similar lifecycle is used for fragments).
Using Fragments also allows you to separate components into their own classes (Fragments), rather than having too much logic in a single Activity. Let me ground that with an example:
Say you're implementing a magazine reader application. using fragments, you could create a fragment: ArticleList, which displays a list of articles, and another fragment: ArticleDisplay, which handles the logic for displaying content. you can then specify how these fragments should interact using the fragments tools, so that on a handset, you can use the full screen real-estate for ArticleDisplay, while on a tablet, you can display the fragments side by side.
If you were to attempt this with an Activity/custom view, you'd have the logic for both Fragments in your monolithic Activity, you'd have to write a custom view, and you'd have to debug this unwieldy monster.
Fragments are, in general, a more sophisticated and powerful way to write your applications. They can do everything an Activity can do, and more. If you don't need the extra functionality, the defaults will probably get you where you need to go, and with less work.