Tuesday, 8 March 2011

Android Developers Blog: The Android 3.0 Fragments API

An important goal for Android 3.0 is to 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:
  • Since the beginning, Android’s UI framework has been designed around the use of layout managers, allowing UIs to be described in a way that will adjust to the space available. A common example is a ListView whose height changes depending on the size of the screen, which varies a bit between QVGA, HVGA, and WVGA aspect ratios.
  • Android 1.6 introduced a new concept of screen densities, making it easy for apps to scale between different screen resolutions when the screen is about the same physical size. Developers immediately started using this facility when higher-resolution screens were introduced, first on Droid and then on other phones.
  • Android 1.6 also made screen sizes accessible to developers, classifying them into buckets: “small” for QVGA aspect ratios, “normal” for HVGA and WVGA aspect ratios, and “large” for larger screens. Developers can use the resource system to select between different layouts based on the screen size.
The combination of layout managers and resource selection based on screen size goes a long way towards helping developers build scalable UIs for the variety of Android devices we want to enable. As a result, many existing handset applications Just Work under Honeycomb on full-size tablets, without special compatibility modes, with no changes required. However, as we move up into tablet-oriented UIs with 10-inch screens, many applications also benefit from a more radical UI adjustment than resources can easily provide by themselves.

Introducing the Fragment

Android 3.0 further helps applications adjust their interfaces with a new class called Fragment. A Fragment is a self-contained component with its own UI and lifecycle; it can be-reused in different parts of an application’s user interface depending on the desired UI flow for a particular device or screen.
In some ways you can think of a Fragment as a mini-Activity, though it can’t run independently but must be hosted within an actual Activity. In fact the introduction of the Fragment API gave us the opportunity to address many of the pain points we have seen developers hit with Activities, so in Android 3.0 the utility of Fragment extends far beyond just adjusting for different screens:
  • Embedded Activities via ActivityGroup were a nice idea, but have always been difficult to deal with since Activity is designed to be an independent self-contained component instead of closely interacting with other activities. The Fragment API is a much better solution for this, and should be considered as a replacement for embedded activities.
  • Retaining data across Activity instances could be accomplished through Activity.onRetainNonConfigurationInstance(), but this is fairly klunky and non-obvious. Fragment replaces that mechanism by allowing you to retain an entire Fragment instance just by setting a flag.
  • A specialization of Fragment called DialogFragment makes it easy to show a Dialog that is managed as part of the Activity lifecycle. This replaces Activity’s “managed dialog” APIs.
  • Another specialization of Fragment called ListFragment makes it easy to show a list of data. This is similar to the existing ListActivity (with a few more features), but should reduce the common question about how to show a list with some other data.
  • The information about all fragments currently attached to an activity is saved for you by the framework in the activity’s saved instance state and restored for you when it restarts. This can greatly reduce the amount of state save and restore code you need to write yourself.
  • The framework has built-in support for managing a back-stack of Fragment objects, making it easy to provide intra-activity Back button behavior that integrates the existing activity back stack. This state is also saved and restored for you automatically.

Honeycomb APIs power tablet-friendly Android apps

Android 3.0, codenamed Honeycomb, introduces a completely new user interface suitable for tablet devices. Google has also extended the platform's APIs so that third-party developers can make their applications work better on large form factors.
The Android 3.0 SDK preview, which was released last week, offers an early look at some of the new features available to developers. We've been scouring the documentation and looking at the source code examples to see how all the pieces fit together. In this article, we will give you a concise overview of several key new features.

ActionBar

One of the most visible changes in Honeycomb applications is the new ActionBar, which replaces the titlebar at the top of the screen. The ActionBar is responsible for displaying the title, the toolbar buttons for significant actions, and a standard menu button that provides access to additional actions that aren't exposed through toolbar buttons.
It's also possible to use the ActionBar for navigation. It provides methods for adding and removing tabs that look like those used for filtering in the new Android 3.0 application drawer. The reference documentation also describes a "list" navigation mode, where the application title in the ActionBar is replaced with a drop-down menu.
Developers can optionally stuff an arbitrary view into the ActionBar, making it possible to populate it with custom widgets and non-standard elements.

Fragments

Another major new feature in the Android 3.0 SDK is the "fragment" system, which makes user interfaces more modular and simplifies the process of developing applications with multiple panes. Developers can use fragments to define user interface pieces that are combined in layouts within an Activity. The application can control how the fragments are displayed to the user, making it possible to conditionally use different presentations depending on screen size and orientation. This is especially useful for building applications that work on both tablets and smartphones.
The FragmentLayout demo that Google bundles with the SDK is a particularly good example of how this capability can be used. It displays a list of Shakespeare plays and will show a text excerpt from each when it is selected from the list. The list itself and all of the individual excerpts are implemented as fragments. The demo has two separate XML layouts: a single-column layout for portrait orientation that shows only the list, and a multi-column layout for landscape orientation that shows the list on the left and a separate pane on the right for the excerpts.
When the user selects a play from the list, the program will determine how to show the excerpt based on the orientation. If the right-hand pane exists (a condition that occurs only when the landscape XML layout is used), the program will display the desired excerpt fragment in that space. If the pane doesn't exist, then the program will assume that it is being used in portrait orientation and will display the text excerpt in a new activity that replaces the list.
The FragmentManager class can be used to control fragment transactions—operations that manipulate the fragments within an activity, such as hiding and showing fragments or replacing one fragment with another. Android can automatically animate the transitions when such changes occur. Developers can also use the FragmentManager to maintain a stack with the history of fragment transactions.
The transaction history comes in handy if you want the user to be able to roll back through fragment changes by hitting the platform's standard back button. There's also a breadcrumb widget that graphically represents the user's position in the fragment stack history. It can be embedded in the ActionBar for easier navigation through the stack.
A specialized kind of fragment called PreferenceFragment makes it easier for developers to create settings pages for configuring their applications. The PreferenceFragment will automatically bind the state of the preference widgets that it hosts with values in a SharedPreferences instance. It builds on the existing capabilities provided by the PreferenceActivity class. When PreferenceFragments are properly used with a PreferenceActivity, the preferences will automatically be displayed in a two-column view on larger screens.

Drag-and-drop

In order to support richer touch-based interaction with Android applications, Google has added generic drag-and-drop APIs. This feature isn't fully documented yet, but there is an instructive example in Google's API demo code. 
The demo displays large dots on the screen and allows the user to drag them by long-pressing. To trap drag-and-drop events, developers can simply assign a callback with the setOnDragListener method. It will pass in a DragEvent object that can be queried to determine if the drag event is the beginning or end of a drag-and-drop operation.

Conclusion

In addition to these new features, Google has also added richer clipboard APIs, an extensible DRM framework, support for processors with multiple cores, and a new hardware-accelerated rendering framework that will improve the performance of Android's user interface drawing. All of these new capabilities bring value to the platform and will help developers build richer and more sophisticated applications.
We would normally provide links to the code examples described above. Unfortunately, Google hasn't published the Android 3.0 documentation or code samples on the official Android reference website yet, but they can be obtained by downloading the SDK. All of the code examples discussed in this article can be found under the samples/android-Honeycomb/ApiDemos subdirectory.
Honeycomb SDK is still a preview release. The APIs are not yet final and are still subject to change, though we think it's unlikely that there will be major changes between now and when the first Honeycomb devices are launched in February. Applications that take advantage of the new features won't be accepted into the Android Market until Google makes the Android 3.0 release final. For more information, you can refer to the SDK preview page on the Android Developer website.