Monday, February 17, 2014

Use of Fragments in Android with Working Example.



Fragment as it says is a part of a substance. Here in android fragment is a part of activity. One activity can have many fragments or alternatively we can say one fragment can be used in many activities. This helps in reusing particulat piece of code too.
This is introduced in Honeycomb API Level 11. In tablet as there are more space,to fill the space fragments are commonly used.
Two Fragments are displayed in Tablet

About the Demo Fragment Application

The application created in this blog will consist of a single activity and two fragments.
One fragment displays the list of friends & second fragment displays the twitter feeds of those friends.
The two fragments will be embedded within the main activity of the application and communication between two fragments happens in such a way that when the list item of  first friend fragment is clicked, twitterfeeds of that friend appears in second fragment .Let's see how.

Creating the Fragment Demo Project

Launch Eclipse and create an Android Application Project named FragmentDemo with the appropriate package name and with minimum required SDK as API 11-Android 3.0(Honeycomb) selections.  creat a blank activity and the use of the default launcher icons. On the New Blank Activity screen of the New Android Application wizard, set the Activity Name to MainActivity

FriendFragment is a ListFragment which displays list of friends name. We are creating dynamically with code like this.
 

package course.labs.fragmentslab;

import android.app.Activity;
import android.app.ListFragment;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class FriendsFragment extends ListFragment {

 private static final String[] FRIENDS = { "Barak Obama", "Clinton",
   "George Bush" };
 
 public interface SelectionListener {
  public void onItemSelected(int position);
 }

 private SelectionListener mCallback;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // use different layout definition, depending on whether device is pre-
  // or post-honeycomb

  int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? android.R.layout.simple_list_item_activated_1
    : android.R.layout.simple_list_item_1;

  // Set the list adapter for this ListFragment
  setListAdapter(new ArrayAdapter(getActivity(), layout, FRIENDS));
 }

  
 @Override
 public void onAttach(Activity activity) {
  super.onAttach(activity);

  // Make sure that the hosting Activity has implemented
  // the SelectionListener callback interface. We need this
  // because when an item in this ListFragment is selected, 
  // the hosting Activity's onItemSelected() method will be called.
  
  try {

   mCallback = (SelectionListener) activity;

  } catch (ClassCastException e) {
   throw new ClassCastException(activity.toString()
     + " must implement SelectionListener");
  }
 }

 // Note: ListFragments come with a default onCreateView() method.
 // For other Fragments you'll normally implement this method.
 //  @Override
 //  public View onCreateView(LayoutInflater inflater, ViewGroup container,
 //  Bundle savedInstanceState)

 
 @Override
 public void onActivityCreated(Bundle savedInstanceState) {
  super.onActivityCreated(savedInstanceState);

  Log.i(TAG, "Entered onActivityCreated()");

  // When using two-pane layout, configure the ListView to highlight the
  // selected list item
  
  if (isInTwoPaneMode()) {

   getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);

  }

 }

 @Override
 public void onListItemClick(ListView l, View view, int position, long id) {

  // Notify the hosting Activity that a selection has been made.

  mCallback.onItemSelected(position);

 }

 // If there is a FeedFragment, then the layout is two-pane 
 private boolean isInTwoPaneMode() {

  return getFragmentManager().findFragmentById(R.id.feed_frag) != null;

 }

}
FeedFragment which displays twitterfeeds is created by inflating feed layout which contains one textview .
Feed layout has this structure.
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/feed_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/greeting" />

</ScrollView>
FeedFragment.java as follows
package course.labs.fragmentslab;

import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FeedFragment extends Fragment {

 private TextView mTextView;
 private static FeedFragmentData feedFragmentData;

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {

  return inflater.inflate(R.layout.feed, container, false);

 }

 @Override
 public void onActivityCreated(Bundle savedInstanceState) {
  super.onActivityCreated(savedInstanceState);

  // Read in all Twitter feeds 
  if (null == feedFragmentData) { 
   
   feedFragmentData = new FeedFragmentData(getActivity());

  }
 }


 // Display Twitter feed for selected feed

 void updateFeedDisplay(int position) {

  Log.i(TAG, "Entered updateFeedDisplay()");
    
  mTextView = (TextView) getView().findViewById(R.id.feed_view);
  mTextView.setText(feedFragmentData.getFeed(position));

 }

}

Adding the Fragments to the Activity

Fragments are attached to MainActivity as follows. MainActivity.java
package course.labs.fragmentslab;

import android.app.Activity;
import android.app.FragmentManager;

import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity implements
  FriendsFragment.SelectionListener {

 private static final String TAG = "Lab-Fragments";

 private FriendsFragment mFriendsFragment;
 private FeedFragment mFeedFragment;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main_activity);

  // If the layout is single-pane, create the FriendsFragment 
  // and add it to the Activity

  if (!isInTwoPaneMode()) {
   
   mFriendsFragment = new FriendsFragment();

   
   FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
   fragmentTransaction.add(R.id.fragment_container, mFriendsFragment);
   fragmentTransaction.commit();
   
   

  } else {

   // Otherwise, save a reference to the FeedFragment for later use

   mFeedFragment = (FeedFragment) getFragmentManager()
     .findFragmentById(R.id.feed_frag);
  }

 }

 // If there is no fragment_container ID, then the application is in
 // two-pane mode

 private boolean isInTwoPaneMode() {

  return findViewById(R.id.fragment_container) == null;
 
 }

 // Display selected Twitter feed

 public void onItemSelected(int position) {

  Log.i(TAG, "Entered onItemSelected(" + position + ")");

  // If there is no FeedFragment instance, then create one

  if (mFeedFragment == null)
   mFeedFragment = new FeedFragment();

  // If in single-pane mode, replace single visible Fragment

  if (!isInTwoPaneMode()) {

   
   FragmentTransaction transaction = getFragmentManager().beginTransaction();
   mFeedFragment.setRetainInstance(true);
   transaction.replace(R.id.fragment_container, mFeedFragment);
   transaction.addToBackStack(null);
   transaction.commit();
   

   // execute transaction now
   getFragmentManager().executePendingTransactions();

  }

  // Update Twitter feed display on FriendFragment
  mFeedFragment.updateFeedDisplay(position);

 }

}
In line no 26 its mentioned that  If the layout is single-pane, create the FriendsFragment  and add it to the Activity. So its added programmatically as


if (!isInTwoPaneMode()) {
                                   
                                    mFriendsFragment = new FriendsFragment();
}
 

FragmentManager()  takes care of managing fragments. Add the FriendsFragments to the fragment_container frame mentioned in main_activity layout.

FragmentManager fragmentManager = getFragmentManager();
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
   fragmentTransaction.add(R.id.fragment_container, mFriendsFragment);
   fragmentTransaction.commit();
On selecting item of FriendFragment it calls the FeedFagment as
public void onItemSelected(int position) {

  Log.i(TAG, "Entered onItemSelected(" + position + ")");

  // If there is no FeedFragment instance, then create one

  if (mFeedFragment == null)
   mFeedFragment = new FeedFragment();

  // If in single-pane mode, replace single visible Fragment

  if (!isInTwoPaneMode()) {

   
   FragmentTransaction transaction = getFragmentManager().beginTransaction();
   mFeedFragment.setRetainInstance(true);
   transaction.replace(R.id.fragment_container, mFeedFragment);
   transaction.addToBackStack(null);
   transaction.commit();
   

   // execute transaction now
   getFragmentManager().executePendingTransactions();

  }

  // Update Twitter feed display on FriendFragment
  mFeedFragment.updateFeedDisplay(position);

 }

}
If  its phone then its single pane mode,in that case friendfragment will be replaced by FeedFragment. If its tablet FeedFragment will be displayed in its side. The code for replacing FriendFragment is
public void onItemSelected(int position) {

  Log.i(TAG, "Entered onItemSelected(" + position + ")");

  // If there is no FeedFragment instance, then create one

  if (mFeedFragment == null)
   mFeedFragment = new FeedFragment();

  // If in single-pane mode, replace single visible Fragment

  if (!isInTwoPaneMode()) {

   
   FragmentTransaction transaction = getFragmentManager().beginTransaction();
   mFeedFragment.setRetainInstance(true);
   transaction.replace(R.id.fragment_container, mFeedFragment);
   transaction.addToBackStack(null);
   transaction.commit();
   

   // execute transaction now
   getFragmentManager().executePendingTransactions();

  }

  // Update Twitter feed display on FriendFragment
  mFeedFragment.updateFeedDisplay(position);

 }

}
Feeds here aren't real time feeds rather its stored as raw data in a text file.
Friend Fragment
Feed Fragment

No comments:

Post a Comment