📜 ⬆️ ⬇️

Fragments API in Android 3.0

In Android 3.0 introduced a new concept of fragments, which serves to simplify the work with the interface for different screen sizes. This topic is a translation of the article from android-developers.blogspot.com. It discusses the advantages of the fragments, and also provides a simple but complete example of an application that works on this principle.

An important goal of Android 3.0 is to simplify the writing of programs that need to be scaled depending on the screen size. For this, the following tools are already available on the Android platform:


The combination of layout managers and the choice of different resources represents a long way to create a scalable interface. As a result, many applications for handsets do not use a special interface for tablets operating under Honeycomb.

Introduction to Fragments


')
Android 3.0 introduces support for new classes that help apps scale their interface, called fragments (Fragment). A fragment is an independent component with its own interface and life cycle; It can be used repeatedly in different parts of the user interface, depending on the desired UI stream for a specific device or screen.

In a sense, you can consider the fragment as a mini-Activity, although it cannot be launched independently and must be placed inside the Activity. In fact, the introduction of the Fragment API gave us the opportunity to solve many problems faced by developers when working with the Activity, since the fragment’s utility extends far beyond the usual settings for different screen resolutions:


Getting started



Here is a simple but complete example of implementing multiple UI threads, using fragments. Let's start with the design landscape landscape'a, containing a list of elements on the left and data on them on the right. This is the layout we need:

image

The code for the Activity is not particularly interesting, it simply calls setContentView () with the following layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment class="com.example.android.apis.app.TitlesFragment" android:id="@+id/titles" android:layout_weight="1" android:layout_width="0px" android:layout_height="match_parent" /> <FrameLayout android:id="@+id/details" android:layout_weight="1" android:layout_width="0px" android:layout_height="match_parent" /> </LinearLayout> 

You can notice the first feature: tag
 <fragment> 
allows you to set a snippet to your interface hierarchy. The above fragment inherits the properties ListFragment, which displays the data on the element in the current location, or in a separate Activity, depending on the layout'a. Notice how the changes in the fragment state are saved.

 public static class TitlesFragment extends ListFragment { boolean mDualPane; int mCurCheckPosition = 0; @Override public void onActivityCreated(Bundle savedState) { super.onActivityCreated(savedState); // Populate list with our static array of titles. setListAdapter(new ArrayAdapter<String>(getActivity(), R.layout.simple_list_item_checkable_1, Shakespeare.TITLES)); // Check to see if we have a frame in which to embed the details // fragment directly in the containing UI. View detailsFrame = getActivity().findViewById(R.id.details); mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE; if (savedState != null) { // Restore last state for checked position. mCurCheckPosition = savedState.getInt("curChoice", 0); } if (mDualPane) { // In dual-pane mode, list view highlights selected item. getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); // Make sure our UI is in the correct state. showDetails(mCurCheckPosition); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("curChoice", mCurCheckPosition); } @Override public void onListItemClick(ListView l, View v, int pos, long id) { showDetails(pos); } /** * Helper function to show the details of a selected item, either by * displaying a fragment in-place in the current UI, or starting a * whole new activity in which it is displayed. */ void showDetails(int index) { mCurCheckPosition = index; if (mDualPane) { // We can display everything in-place with fragments. // Have the list highlight this item and show the data. getListView().setItemChecked(index, true); // Check what fragment is shown, replace if needed. DetailsFragment details = (DetailsFragment) getFragmentManager().findFragmentById(R.id.details); if (details == null || details.getShownIndex() != index) { // Make new fragment to show this selection. details = DetailsFragment.newInstance(index); // Execute a transaction, replacing any existing // fragment with this one inside the frame. FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.details, details); ft.setTransition( FragmentTransaction.TRANSIT_FRAGMENT_FADE); ft.commit(); } } else { // Otherwise we need to launch a new activity to display // the dialog fragment with selected text. Intent intent = new Intent(); intent.setClass(getActivity(), DetailsActivity.class); intent.putExtra("index", index); startActivity(intent); } } } 

You also need to implement the DetailsFragment, which will display the data for the item in a regular TextView.

 public static class DetailsFragment extends Fragment { /** * Create a new instance of DetailsFragment, initialized to * show the text at 'index'. */ public static DetailsFragment newInstance(int index) { DetailsFragment f = new DetailsFragment(); // Supply index input as an argument. Bundle args = new Bundle(); args.putInt("index", index); f.setArguments(args); return f; } public int getShownIndex() { return getArguments().getInt("index", 0); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (container == null) { // Currently in a layout without a container, so no // reason to create our view. return null; } ScrollView scroller = new ScrollView(getActivity()); TextView text = new TextView(getActivity()); int padding = (int)TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 4, getActivity().getResources().getDisplayMetrics()); text.setPadding(padding, padding, padding, padding); scroller.addView(text); text.setText(Shakespeare.DIALOGUE[getShownIndex()]); return scroller; } } 

It's time to add another UI thread to our application. When the screen is in portrait mode, there is not enough space to display two fragments side by side. That is, we want to display only the list:

image

Let's write a new layout for portrait orientation:

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment class="com.example.android.apis.app.TitlesFragment" android:id="@+id/titles" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> 

Now we have no container for displaying data for the TitlesFragment, only the list is displayed. When you click on the list item, you now need to call a separate Activity, in which the data will be displayed:

image

Now, all that is required of us is to use the ready-made DetailsFragment:
 public static class DetailsActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { // If the screen is now in landscape mode, we can show the // dialog in-line so we don't need this activity. finish(); return; } if (savedInstanceState == null) { // During initial setup, plug in the details fragment. DetailsFragment details = new DetailsFragment(); details.setArguments(getIntent().getExtras()); getSupportFragmentManager().beginTransaction().add( android.R.id.content, details).commit(); } } } 

By connecting the Activity, we get a fully working example of an application that uses a radical change in the UI of the flow, based on what configuration is currently being used. Also, the application is automatically adjusted to the screen size requirements when changing configuration.

This example illustrates just one way to use snippets to fit your UI. Depending on the design, you may prefer others. For example, you can put all your application into one Activity, in which the structure of fragments will change.

As usual, more information can be found in the SDK documentation. You can also find examples in ApiDemos.

Fragmentation for all


Fragment API will be useful for developers who are starting to work with apps that are oriented on tablets that are designed for Android 3.0, in many cases related to the big screen. Also, the use of fragments should make it easier to configure the UI for applications for new Android devices, such as TVs.

However, now the Fragment API will be most in demand to improve the interface of existing applications for phones for tablets.

It is also planned to make a static library for using the Fragment API ( Hurray !!! ), in order to use the method described above on earlier versions of Android. In fact, all the code in the example uses just a static class library, and it runs on Android 2.3 (you can compare with the examples in the Android 3.0 SDK, they are almost the same). Our goal is to make these APIs as similar as possible so that you can start working with them now, regardless of when you switch to Android 3.0.

While there is no exact date when the library will be available, but it will definitely be soon. For now, you can start working with snippets on Android 3.0.

Source: https://habr.com/ru/post/113196/


All Articles