Pr.Pg Next Pg

Fragments Tutorials

 

Introduction

  • A Fragment is a piece of an application's user interface or behavior that can be placed in an Activity which enable more modular activity design.

  • It will not be wrong if we say, a fragment is a kind of sub-acitivity.

  • Fragments can be dynamically or statically added to a layout. A Fragment encapsulate functionality so that it is easier to reuse within activity and layouts.

  • Fragment component runs in the context of an activity but it has its own lifecycle and their own user interface.

  • You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities.

  • A fragment must always be embedded in an activity and the fragment's lifecycle is directly affected by the host activity's lifecycle. For example, when the activity is paused, so are all fragments in it, and when the activity is destroyed, so are all fragments. 

  •  A fragment is not always required to be a part of the activity layout; you may also use a fragment without its own UI as an invisible worker for the activity.

 


Creating a Fragment

  • To create a fragment, you must create a subclass of Fragment (or an existing subclass of it). The Fragmentclass has code that looks a lot like an Activity.

  • It contains callback methods similar to an activity, such as onCreate(), onStart(), onPause(), andonStop().

  • An Life cycle of a Fragment is similar to that of an Activity.

  • To provide a user interface to the fragment, you must implement the  onCreateView() callback method, which the Android system calls when it's time for the fragment to draw its layout. Your implementation of this method must return a View that is the root of your fragment's layout.

  • This method is called when the fragment is to draw its interface for the first time.

  • Below is an example which shows how to add the interface to the fragment in the form of layout.

 

 

 

 

 

public class Fragment1 extends Fragment {

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

// TODO Auto-generated method stub

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

}

}

 

 

 

 

 

 

  • The inflate() method takes three arguments:

  • The resource ID of the layout you want to inflate.

  • The ViewGroup to be the parent of the inflated layout. Passing the container is important in order for the system to apply layout parameters to the root view of the inflated layout, specified by the parent view in which it's going.

  • A boolean indicating whether the inflated layout should be attached to the ViewGroup (the second parameter) during inflation. (In this case, this is false because the system is already inserting the inflated layout into the container—passing true would create a redundant view group in the final layout.)

 

Adding Fragment to Activity

  • There are two ways to add a fragment to an Activity.

  • Adding Fragment by declaring it inside the activities layout.

  • Below is an example in which we specify the layout properties for a fragment as if it were a view.

 

 

 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:weightSum="2">

 

<fragment

android:id="@+id/listFragment"

android:layout_width="match_parent"

android:layout_weight="1"

android:layout_height="match_parent"

android:layout_marginTop="?android:attr/actionBarSize"

class="com.example.helloandroid.Fragment1"></fragment>

 

<fragment

android:id="@+id/detailFragment"

android:layout_weight="1"

android:layout_width="match_parent"

android:layout_height="match_parent"

class="com.example.helloandroid.Fragment2">

<!-- Preview: layout=@layout/details -->

</fragment>

</LinearLayout>

 

  • The class attribute specifies the name of the Fragments class to instantiate the layout.

  • The other attributes defined are similar to that of a view.

  • In this case our activity will have two fragments.

  • Adding the Fragment programitically.

  • Below is an example in which we add the fragment in the java file of the activity.

  • In this case we set the layout for each fragment programitically and then add them to the activity.

  • To make fragment transactions in your activity (such as add, remove, or replace a fragment), you must use APIs from FragmentTransaction.

  • You can then add a fragment using the add() method, specifying the fragment to add and the view in which to insert it.

  • The first argument passed to add() is the ViewGroup in which the fragment should be placed, specified by resource ID, and the second parameter is the fragment to add.

  • Once you've made your changes with FragmentTransaction, you must call commit() for the changes to take effect.

 

 

 

package com.example.helloandroid;

 

import android.os.Bundle;

import android.app.Activity;

import android.app.FragmentManager;

import android.app.FragmentTransaction;

import android.view.Menu;

import android.view.View;

import android.widget.LinearLayout;

 

public class Fragments extends Activity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(CreateUI());

}

 

View CreateUI() {

LinearLayout layout_main = new LinearLayout(this);

layout_main.setWeightSum(2);

 

LinearLayout layout1 = new LinearLayout(this);

 

layout1.setOrientation(LinearLayout.VERTICAL);

layout1.setLayoutParams(new LinearLayout.LayoutParams(

LinearLayout.LayoutParams.MATCH_PARENT,

LinearLayout.LayoutParams.MATCH_PARENT, 1));

layout1.setId(0x101);

FragmentManager fm1 = getFragmentManager();

FragmentTransaction ft1 = fm1.beginTransaction();

Fragment1 f1 = new Fragment1();

Fragment2 f2 = new Fragment2();

ft1.add(0x101, f1, "f1");

ft1.commit();

layout_main.addView(layout1);

LinearLayout layout2 = new LinearLayout(this);

 

layout2.setOrientation(LinearLayout.VERTICAL);

layout2.setLayoutParams(new LinearLayout.LayoutParams(

LinearLayout.LayoutParams.MATCH_PARENT,

LinearLayout.LayoutParams.MATCH_PARENT, 1));

layout2.setId(0x102);

{

FragmentManager fm2 = getFragmentManager();

FragmentTransaction ft2 = fm2.beginTransaction();

ft2.add(0x102, f2, "f2");

ft2.commit();

layout_main.addView(layout2);

}

return layout_main;

}

}

 

 

 

 

 

 

 

Fragments without UI

  • You can also add fragments without UI.

  • In that case, we use add(Fragment, String) method, where the second parameter is the unique string tag.

  • Since the fragment does not have a User Interface, there wont be any call made to the onCreateView() method, you can also return null from the method.

 

Other methods

  • There are many other methods which you can use on a fragment for transactions to make the activity capable of adding,removing,replacing and perform other actions with them.

  • In order to do so you need an instance of Fragment Transaction from the FragmentManager.

  • We have already shown how to do that in the previous example.

  • Before you call commit(), however, you might want to call addToBackStack(), in order to add the transaction to a back stack of fragment transactions.

  • This back stack is managed by the activity and allows the user to return to the previous fragment state, by pressing the Back button.

  • We can also set the transition for our transactions by using the setTransition() before committing.

 

Event CallBacks to the Activity

  • Sometimes we might want the fragments to share the events with the activity.

  • In order to do so we define a callback interface inside the fragment and this interface has to be implemented by the host activity.

 

 

 

//Container activity implements the interface

public void onItemSelected(String text) {

Fragment2 fragment = (Fragment2)getFragmentManager()

.findFragmentById(R.id.detailFragment);

if (fragment != null&& fragment.isInLayout()) {

fragment.setDisplayText(text);

}

 

  • To ensure that the host activity implements this interface, fragment’s onAttach() callback method (which the system calls when adding the fragment to the activity) instantiates an instance of the interface by casting the Activity that is passed into onAttach().

 

 

 

 

 

public class Fragment1 extends ListFragment {

private onItemSelectedListener listener;

@Override

public void onAttach(Activity activity) {

super.onAttach(activity);

if (activity instanceof onItemSelectedListener) {

listener = (onItemSelectedListener) activity;

} else {

throw new ClassCastException(activity.toString()

+ " must implemenet MyListFragment.OnItemSelectedListener");

}

}

 

Application With Two Fragments

  • We are now going to demonstrate an application, which will have two fragments

  • One fragment which will be a ListFragment and other one will contain a TextView which will show which Item in the List of the first fragment was clicked.

  • First we start by making the layouts for the fragment2.

  • The first fragment is a ListFragment so it automatically gets the ListView and the onCreateView() method is not called.

  • Below are the layouts for the fragment2.

 

 

layout_fragment2.xml

 

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

 

<TextView

android:id="@+id/tvFragment"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerHorizontal="true"

android:layout_centerVertical="true"

android:text="" />

 

</RelativeLayout>

 

 

  • We now check out the class files for the Fragments.

  • For the Fragment1 we set the List View and then also share the ListItemClick information with the activity using the onAttach() method as explained before.

 

 

Fragment1.java

 

package com.example.helloandroid;

 

import android.app.Activity;

import android.app.ListFragment;

import android.os.Bundle;

import android.view.View;

import android.widget.ArrayAdapter;

import android.widget.ListView;

 

public class Fragment1 extends ListFragment {

String[] s = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6",

"Item 7" };

private onItemSelectedListener listener;

 

publicinterface onItemSelectedListener {

public void onItemSelected(String text);

}

 

@Override

public void onCreate(Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),

android.R.layout.simple_list_item_1, s);

setListAdapter(adapter);

}

 

@Override

public void onAttach(Activity activity) {

super.onAttach(activity);

if (activity instanceof onItemSelectedListener) {

listener = (onItemSelectedListener) activity;

} else {

thrownew ClassCastException(activity.toString()

+ " must implemenet MyListFragment.OnItemSelectedListener");

}

}

 

@Override

public void onListItemClick(ListView l, View v, int position, long id) {

// TODO Auto-generated method stub

super.onListItemClick(l, v, position, id);

listener.onItemSelected(s[position]);

 

}

 

}

 

 

  • Also we define the class for our other Fragment in which we take in the text using the method setDisplayText() and set up our TextView.

  • Below is the code for it.

 

 

Fragment2.java

 

package com.example.helloandroid;

 

import android.app.Fragment;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.TextView;

 

public class Fragment2 extends Fragment {

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

// TODO Auto-generated method stub

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

}

public void setDisplayText(String s){

TextView t = (TextView)getView().findViewById(R.id.tvFragment);

t.setText(s);

}

 

}

 

 

  • We will now discuss the Fragments activity class in which we will implement the interface and in the method onItemSelected() we will call the method SetDisplayText() inside the Fragment2 by getting its reference from the FragmentManager using the findFragmentById().

  • Make sure you define this activity in Manifest.

  • Also like we have discussed earlier, if you want to save the state on orientation change, you can add the following attribute for your activity.

  • android:configChanges="keyboardHidden|orientation|screenSize"

  • Below is the code for the activity.

 

 

Fragments.java

 

package com.example.helloandroid;

 

import android.app.Activity;

import android.os.Bundle;

public class Fragments extends Activity implements Fragment1.onItemSelectedListener

{

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_fragment);

}

 

//Container activity implements the interface

public void onItemSelected(String text) {

Fragment2 fragment = (Fragment2)getFragmentManager()

.findFragmentById(R.id.detailFragment);

if (fragment != null&& fragment.isInLayout()) {

fragment.setDisplayText(text);

}

}

 

}

  • Following are the screenshots of the Application when you run it. You can see both the fragments in portrait as well as landscape mode.

 

 

Pr.Pg border                                              Next Pg