Thursday, January 12, 2012

Android Fragment

Fragment is being hanging out since Andriod 3.0, but with the release of 4.0, it has become an obvious choice for Android Application development for both Tabs and Smart phones. Few people think, fragment is a "Superman" which can add any kind of UI layout/style/decoration. But that is not true, rather than being an UI layout or decoration enhancer, Fragment is a very important concept to manage segments of your UI component code base.

Prior to Fragment, developers were able manage UI flow only at the Activity level. All UI components were Views (mentioned in XML layout and part of Activity) and there was no way to manage these components separately. As a result all view management code were in a single file i.e. Activity class. With fragment approach, we can now remove View management code from Activity and place them in their respective Java classes. So, a pretty neat approach for code management.

Here I'll explain various concepts of Fragment with an example application, which has a split layout- List Fragment on Left and Image Viewer fragment on Right. It explains ListFragment, Dynamic fragment width management, switching fragments and back stack concept.

So, how do we add a fragment ? 
Define a container layout (LinearLayout) and add [fragment] tag inside. Inside the fragment tag, we need to mention respective Fragment Java class.

[LinearLayout 
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/list_frag_layout"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:background="#FFFFFF"]
       [fragment 
            android:name="com.pras.frags.MyListFrag"
            android:id="@+id/list_frag"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/]
[/LinearLayout]

Here list_frag_layout is the container layout of list_frag. 

We need to attach this layout with an Activity. The Activity class is the parent of the fragment and it gives callback to onAttach() and onContentView() methods of fragment.

How does the Fragment communicates with Activity ?
A fragment can get the instance of its parent Activity by calling getActivity() or during the onAttach() callback, Framework passes the instance of parent Activity to fragment.
You can define an Interface and the Activity should implement that interface. Fragment class can give call to this Interface method to notify any UI event.
An activity can hold multiple Fragments and fragments should communicate via their parent Activity. 

How do I dynamically manage the width/height of Fragment ?
To achieve this we need to keep the fragment inside a container layout, just like above. Following code piece set the width of list_frag to 50% of the screen.
int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
int leftFragWidth = (int)(screenWidth * 0.50);
LinearLayout.LayoutParams leftParm = new LinearLayout.LayoutParams(leftFragWidth, LinearLayout.LayoutParams.MATCH_PARENT);
findViewById(R.id.list_frag_layout).setLayoutParams(leftParm);
How do I switch multiple Fragments ?
In this example, when user click on any list item, it switch to Detail Fragment. To switch/replace fragment, we need to use Fragment Transaction and hide the previous i.e. ListFragment. To get the benefit of BACK handling, we'll add this switch transaction to the Back Stack. So user can go to the List pressing the Back key. It is really a nice concept.
Following code piece adds Detail Fragment on View and hides the previous fragment i.e. List. To keep track of this transaction, it will add this in Back Stack and finally commit the transaction.
           // Change List fragment with Detail Fragment
        FragmentManager fm = getFragmentManager();
        FragmentTransaction transaction = fm.beginTransaction();
        // Hide previous fragment
        transaction.hide(fm.findFragmentById(R.id.list_frag));
        // Add this new Fragment into the layout
        DetailFrag detailFrag = new DetailFrag();
        transaction.add(R.id.list_frag_layout, detailFrag);
        // Add to this transaction into BackStack
        transaction.addToBackStack(null);
        // Commit this transaction
        transaction.commit();


You can download the complete Fragment example source code from http://code.google.com/p/android-java-sample-code/