0% found this document useful (0 votes)
116 views39 pages

Lesson06 Fragments

vbhjkl

Uploaded by

Mohamed Aashim
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
116 views39 pages

Lesson06 Fragments

vbhjkl

Uploaded by

Mohamed Aashim
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 39

Lesson 6.

Fragments

Android Fragments .............................................................................................3


Lesson 6
Android Fragments

Goals

The Android Eco-System


Parallelism through Fragments

Fragment's Life Cycle

1 2 3 4 5 6 7 8 9 10  11 

onAttach onCreate onCreateView onACtivityCreated onStart onResume onPause onStop onDestroyView onDestroy onDetach

Created Started Resumed Paused Stopped Destroyed


Rules for Inter-Fragment Communication



Integrating the Home Activity and its Fragments


<fragment>
android:name=fragmentName

Dynamic Binding
FragmentTransaction
add()
replace()

FragmentManager
FragmentTransaction ft= getFragmentManager().beginTransaction();

FragmentBlue blueFragment= FragmentBlue.newInstance("some_param_value");

ft.replace(R.id.main_holder_blue, blueFragment);

ft.commit();

// create a new BLUE fragment - show it


ft = getFragmentManager().beginTransaction();
blueFragment = FragmentBlue.newInstance("new-blue");
ft.replace(R.id.main_holder_blue, blueFragment);
ft.commit();

// create a new RED fragment - show it


ft = getFragmentManager().beginTransaction();
redFragment = FragmentRed.newInstance("new-red");
ft.replace(R.id.main_holder_red, redFragment);
ft.commit();
Note

import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.Fragment;

Example 6.1 An App using Dynamic Fragment Binding

TextView
TextView
MainActivity FragmentBlue FragmentRed
IFragmentCallbacks IMainCallbacks
MainActivity MainActivity
activity_main.xml layout_blue.xml layout_red

<?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:baselineAligned="false"
android:padding="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/txtHomeMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffea00"
android:layout_marginBottom="10dp"
android:text="MainActivity area"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/main_holder_blue"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#220000ff"
android:orientation="vertical"/>
<FrameLayout
android:id="@+id/main_holder_red"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:background="#22ff0000"
android:orientation="vertical"/>
</LinearLayout>
</LinearLayout>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_blue"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#220000FF"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1Blue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Blue Layout..."
android:textColor="@android:color/white"
android:background="#0000FF"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ListView
android:id="@+id/listView1Blue"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>

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


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_red"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#22FF0000"
android:orientation="vertical">
<TextView
android:id="@+id/textView1Red"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#d50000"
android:text="Red Layout..."
android:textColor="@android:color/white"
android:textAppearance="?android:attr/textAppearanceLarge" />
<Button
android:id="@+id/button1Red"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:ems="10"
android:text="Click me!" />
</LinearLayout>

package csu.matos;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

//-----------------------------------------------------------------------
// GOAL: This example shows an Activity that includes two fragments.
// Fragments inflate layouts and then get attached to their corresponding
// layouts in the UI. The example includes two interfaces IMainCallbacks
// and IFragmentCallbacks. They implement inter-process communication from
// Main-to-fragments and from Fragments-to-Main.
// -----------------------------------------------------------------------
public class MainActivity extends FragmentActivity implements IMainCallbacks {

FragmentTransaction ft;
FragmentRed redFragment;
FragmentBlue blueFragment;
TextView txtHomeMsg;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtHomeMsg = (TextView) findViewById(R.id.txtHomeMsg);

// create a new BLUE fragment - show it


ft = getSupportFragmentManager().beginTransaction();
blueFragment = FragmentBlue.newInstance("first-blue");
ft.replace(R.id.main_holder_blue, blueFragment);
ft.commit();

// create a new RED fragment - show it


ft = getSupportFragmentManager().beginTransaction();
redFragment = FragmentRed.newInstance("first-red");
ft.replace(R.id.main_holder_red, redFragment);
ft.commit();

// MainCallback implementation (receiving messages coming from Fragments)


@Override
public void onMsgFromFragToMain(String sender, String strValue) {
// show message arriving to MainActivity
txtHomeMsg.setText("Sender=" + sender + " Message=" + strValue);
Toast.makeText(getApplication(),
" MAIN GOT>> " + sender + "\n" + strValue, Toast.LENGTH_LONG)
.show();

if (sender.equals("RED-FRAG")) {
// TODO: if needed, do here something on behalf of the RED fragment
}

if (sender.equals("BLUE-FRAG")) {
try {
// forward blue-data to redFragment using its callback method
redFragment.onMsgFromMainToFragment("\nSender: " + sender
+ "\nMsg: " + strValue);

} catch (Exception e) {
Log.e("ERROR", "onStrFromFragToMain " + e.getMessage());
}
}

beginTransaction commit

newInstance

activity_main.xml

onMsgFromFragToMain IMainCallbacks
redFragment blueFragment MainActivity

blueFragment redFragment
onMsgFromMainToFragment
import android.support.v4.app.Fragment;
import ...

public class FragmentBlue extends Fragment {


// this fragment shows a ListView
MainActivity main;
Context context = null;
String message = "";

// data to fill-up the ListView


private String items[] = { "Text-on-Line-00", "Text-on-Line-01",
"Text-on-Line-02", "Text-on-Line-03", "Text-on-Line-04",
"Text-on-Line-05", "Text-on-Line-06", "Text-on-Line-07",
"Text-on-Line-08", "Text-on-Line-09", "Text-on-Line-10", };

// convenient constructor(accept arguments, copy them to a bundle, binds bundle to fragment)


public static FragmentBlue newInstance(String strArg) {
FragmentBlue fragment = new FragmentBlue();
Bundle args = new Bundle();
args.putString("strArg1", strArg);
fragment.setArguments(args);
return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
context = getActivity(); // use this reference to invoke main callbacks
main = (MainActivity) getActivity();
} catch (IllegalStateException e) {
throw new IllegalStateException(
"MainActivity must implement callbacks");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

// inflate res/layout_blue.xml to make GUI holding a TextView and a ListView


LinearLayout layout_blue = (LinearLayout) inflater.inflate(R.layout.layout_blue, null);

// plumbing – get a reference to textview and listview


final TextView txtBlue = (TextView) layout_blue.findViewById(R.id.textView1Blue);
ListView listView = (ListView) layout_blue.findViewById(R.id.listView1Blue);
listView.setBackgroundColor(Color.parseColor("#ffccddff"));

// define a simple adapter to fill rows of the listview


ArrayAdapter<String> adapter = new ArrayAdapter<String>(context,
android.R.layout.simple_list_item_1, items);
listView.setAdapter(adapter);
// show listview from the top
listView.setSelection(0);
listView.smoothScrollToPosition(0);

// react to click events on listview’s rows


listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// inform enclosing MainActivity of the row’s position just selected
main.onMsgFromFragToMain("BLUE-FRAG", "Blue selected row=" + position);
txtBlue.setText("Blue selected row=" + position);
}
});

// do this for each row (ViewHolder-Pattern could be used for better performance!)
return layout_blue;

}// onCreateView
}// class

Class.newInstance()

Bundle
<key,value>
setArguments()

onCreate() MainActivity
MainActivity

onCreateView()
layout_blue.xml TextView
ListView

ArrayAdapter ListView

ListView
onMsgFromFragToMain

import android.support.v4.app.Fragment;
import ...

public class FragmentRed extends Fragment implements IFragmentCallbacks {


MainActivity main;
TextView txtRed;
Button btnRedClock;

public static FragmentRed newInstance(String strArg1) {


FragmentRed fragment = new FragmentRed();
Bundle bundle = new Bundle();
bundle.putString("arg1", strArg1);
fragment.setArguments(bundle);
return fragment;
}// newInstance

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Activities containing this fragment must implement interface: IMainCallbacks
if (!(getActivity() instanceof IMainCallbacks)) {
throw new IllegalStateException( " Activity must implement IMainCallbacks");
}
main = (MainActivity) getActivity(); // use this reference to invoke main callbacks
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflate res/layout_red.xml which includes a textview and a button
LinearLayout view_layout_red = (LinearLayout) inflater.inflate(
R.layout.layout_red, null);
// plumbing - get a reference to widgets in the inflated layout
txtRed = (TextView) view_layout_red.findViewById(R.id.textView1Red);

// show string argument supplied by constructor (if any!)


try {
Bundle arguments = getArguments();
String redMessage = arguments.getString("arg1", "");
txtRed.setText(redMessage);
} catch (Exception e) {
Log.e("RED BUNDLE ERROR - ", "" + e.getMessage());
}
// clicking the button changes the time displayed and sends a copy to MainActivity
btnRedClock = (Button) view_layout_red.findViewById(R.id.button1Red);
btnRedClock.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
String redMessage = "Red clock:\n" + new Date().toString();
txtRed.setText(redMessage);
main.onMsgFromFragToMain("RED-FRAG", redMessage);
}
});
return view_layout_red;
}

@Override
public void onMsgFromMainToFragment(String strValue) {
// receiving a message from MainActivity (it may happen at any point in time)
txtRed.setText("THIS MESSAGE COMES FROM MAIN:" + strValue);
}

}// FragmentRed
FragmentBlue

newInstance

FragmentRed onCreate() MainActivity

FragmentRed MainActivity
onMsgFromMainToFragment

blueFragment

public interface IMainCallbacks {

public void onMsgFromFragToMain (String senderId, String strMsg);

public interface IFragmentCallbacks {

public void onMsgFromMainToFragment(String strValue);

Fragments MainActivity onCreate()

Example 6.2 Static Fragment Binding

MainActivity FragmentRed
FragmentBlue

layout_red.xml layout_blue.xml


<fragment>

1. android:name="AppPackageName.FragmentClassName"

2. android:id="@id+/uniqueName"

3. android:tag="string"

<?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:baselineAligned="false"
android:orientation="vertical"
android:padding="16dp">

<TextView
android:id="@+id/txtHomeMsg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:background="#ffea00"
android:text="MainActivity area"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">

<fragment
android:id="@+id/main_holder_blue"
android:name="csu.matos.FragmentBlue"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>

<fragment
android:id="@+id/main_holder_red"
android:name="csu.matos.FragmentRed"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"/>
</LinearLayout>
</LinearLayout>

package csu.matos;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.Fragment;
import ...
//-----------------------------------------------------------------------
// GOAL: This example shows an Activity that includes two fragments.
// Fragments inflate layouts and then get attached to their corresponding
// layouts in the UI. The example includes two interfaces IMainCallbacks
// and IFragmentCallbacks. They implement inter-process communication from
// Main-to-fragments and from Fragments-to-Main.
// -----------------------------------------------------------------------
public class MainActivity extends FragmentActivity implements IMainCallbacks {

FragmentTransaction ft;
FragmentRed redFragment;
FragmentBlue blueFragment;
TextView txtHomeMsg;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtHomeMsg = (TextView) findViewById(R.id.txtHomeMsg);

// NOTHING to do, fragments will be automatically created and added to the GUI
}

@Override
public void onAttachFragment(Fragment fragment) {
super.onAttachFragment(fragment);
// (just in case...) get a reference to each fragment now attached to the GUI
if (fragment.getClass() == FragmentRed.class ){
redFragment = (FragmentRed) fragment;

}
if (fragment.getClass() == FragmentBlue.class ){
blueFragment = (FragmentBlue) fragment;

}
}

// MainCallback implementation (receiving messages coming from Fragments)


@Override
public void onMsgFromFragToMain(String sender, String strValue) {
// show message arriving to MainActivity
txtHomeMsg.setText("Sender=" + sender + " Message=" + strValue);
Toast.makeText(getApplication(), " MAIN GOT>> " + sender
+ "\n" + strValue, Toast.LENGTH_LONG).show();

if (sender.equals("RED-FRAG")) {
// TODO: if needed, do here something on behalf of the RED fragment
}

if (sender.equals("BLUE-FRAG")) {
try {
// forward blue-data(master) to redFragment(detail) using its callback method
redFragment.onMsgFromMainToFragment("\nSender: " + sender
+ "\nMsg: " + strValue);

} catch (Exception e) {
Log.e("ERROR", "onStrFromFragToMain " + e.getMessage());
}
}

FragmentRed FragmentBlue layout_red.xml layout_blue.xml

onCreate() onCreateView()
android:name="csu.matos.FragmentXYZ"

onAttachFragment
redFragment blueFragment

onMsgFromFragToMain blueFragment MainActivity


blueFragment redFragment

Fragment FragmentACtivity
FragmentTransaction
Example 6.3 Mixed Mode Binding
Fragment1Blue
Fragment2Red
Fragment3Orange
IFragmentCallbacks
MainActivity MainActivity IMainCallbacks

EditText MainActivity

activity_main.xml
fragment1Blue layout2_red.xml layout_red.xml

<LinearLayout android:id="@+id/home0"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/white"
android:padding="16dp">
<TextView
android:id="@+id/txtMsgMain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:background="#FFFFEA00"
android:textSize="25sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="10dp"
android:orientation="horizontal">
<fragment
android:id="@+id/home1"
android:name="csu.matos.matos.Fragment1Blue"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<View
android:layout_width="5dp"
android:layout_height="match_parent"
android:layout_margin="3dp"
android:background="#616161"/>
<fragment
android:id="@+id/home2"
android:name="csu.matos.matos.Fragment2Red"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_margin="1dp"
android:background="#616161"/>
<LinearLayout
android:id="@+id/home3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="2dp"
android:layout_weight="2"
android:background="#e0e0e0"
android:orientation="vertical"
android:padding="1dp"/>
</LinearLayout>

<LinearLayout> home3
Fragment3Orange, i
<?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:background="#ffcc80"
android:orientation="vertical"
android:padding="3dp">
<TextView
android:id="@+id/txtMsg3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E65100"
android:gravity="center"
android:padding="2dp"
android:text="THIS IS LAYOUT3"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/white"/>
<EditText
android:id="@+id/ediBox3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Enter some data here"
android:inputType="none"/>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"/>
<Button
android:id="@+id/btnGo3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="5"
android:background="@android:drawable/btn_default"
android:text="Go"/>
</LinearLayout>

ActivityMain.java

import android.app.Fragment; // not using compatibility lib


import android.app.FragmentTransaction;
import ...

public class MainActivity extends Activity implements IMainCallbacks {

//plumbing: defining space for three fragments to be shown


TextView txtMsgMain;
LinearLayout home3;
Fragment1Blue frag1Blue;
Fragment2Red frag2Red;
Fragment3Orange frag3Orange;
// var used to save values returned from fragments
String mainStrValue = "n.a.";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtMsgMain =(TextView)findViewById(R.id.txtMsgMain);
home3 = (LinearLayout)findViewById(R.id.home3);

// create f3 (Fragment3Orange), pass to it a string param, collocate f3 into home3 UI area


FragmentTransaction fragTransMngr3 = getFragmentManager().beginTransaction();
Bundle args3 = new Bundle();
args3.putString("strParam", "Hello world");
Fragment3Orange f3 = new Fragment3Orange();
f3.setArguments(args3);
fragTransMngr3.replace(home3.getId(), f3, "F3TAG");
fragTransMngr3.commit();
}

@Override
public void onAttachFragment(Fragment fragment) {
super.onAttachFragment(fragment);
// get a reference to each fragment attached to the GUI
if (fragment.getClass() == Fragment1Blue.class) {
frag1Blue = (Fragment1Blue) fragment;
}
if (fragment.getClass() == Fragment2Red.class) {
frag2Red = (Fragment2Red) fragment;
}
if (fragment.getClass() == Fragment3Orange.class) {
frag3Orange = (Fragment3Orange) fragment;
}
}

@Override
public void onMsgFromFragmentToMain(String sender, String strValue) {
txtMsgMain.setText(sender + " strValue= " + strValue);
if (sender.equals("Frag1Blue")){
// Dynamically identify current fragment inside a given UI container: (1) use
// findFragmmebtById(...) to get a reference to current fragment hosted by UI,
// (2) then send a message to the fragment.
Fragment2Red redFrag = (Fragment2Red)getFragmentManager().findFragmentById(R.id.home2);
redFrag.onMsgFromMainToFragment("1Main says..." + strValue);
// NOTE: the state method onFragmentAttached already saved a reference to the red
// fragment in the global variable: frag2Red. Consequently the above code is
// equivalent to: frag2Red.onMsgFromMainToFragment("2Main says..." + strValue);
}
}

}
MainActivity onCreate, onAttachFragment onMsgFromFragentToMain
onCreate TextBox
onAttachFragment
onMsgFromFragmentToMain

frag1Blue
frag2Red Fragment1Blue Fragment2Red
IMainCallbacks IFragmentCallbacks
Fragment3Orange

public class Fragment3Orange extends Fragment {


// a reference to superclass hosting this fragment
IMainCallbacks mainCallbackRef;

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

// TODO: do this inside try-catch or check instanceOf...


mainCallbackRef = (IMainCallbacks) getActivity();

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// echo supplied input parameter
String arg1 = getArguments().getString("strParam");
Log.e("Fragment3", "I got strParam=" + arg1);

// inflate a layout showing a textbox and a button


// do plumbing, get access to textbox and button-clicking
LinearLayout layout3 = (LinearLayout) inflater.inflate(R.layout.layout3_orange, null);
TextView txtMsg3 = (TextView) layout3.findViewById(R.id.txtMsg3);
final EditText ediBox3 = (EditText) layout3.findViewById(R.id.ediBox3);

Button btnGo3 = (Button) layout3.findViewById(R.id.btnGo3);


btnGo3.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
String text = ediBox3.getText().toString();
Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show();
mainCallbackRef.onMsgFromFragmentToMain("LAYOUT3-INT", text + " " + new Date());
}
});
// layout has been set
return layout3;
}
@Override
public void onPause() {
// save any important data here (row indices, textbox content)
super.onPause();
}

@Override
public void onDestroy() {
// the end is near! - release your possessions
super.onDestroy();
mainCallbackRef = null;
}
}

Saving Fragment's State Data

onSaveInstanceState

onCreate onCreateView onViewCreated onViewStateRestored

onRestoreInstanceState

saveInstanceState

savedInstanceState
.

if (savedInstanceState == null) {
//cold-start: create new fragment, pass arguments, add or replace fragment to UI
FragmentTransaction fragTransMngr = getFragmentManager().beginTransaction();
Bundle args = new Bundle();
args.putString("strParam1", "some string value here...");
frag = new YourFragment();
frag.setArguments(args);
fragTransMngr.replace(fragmentContainerInsideHostUI.getId(), frag, "FRAGMENT-TAG");
fragTransMngr.commit();
}
@Override
public void onCreate(Bundle savedInstanceState) {
...
String initialData = getArguments().getString("arg1", "cold-start-default-value");
...
if (savedInstanceState != null){
// warm-start: reusing fragments, extract state data from saved bundle
stateData1 = savedInstanceState.getString("stateData1","str-warm-default-1");
stateData2 = savedInstanceState.getInt("stateData2", int-warm-default-2);
}
}//onCreate
...

//use next method to temporarily save fragment's state data


@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("stateData1", someStringToBeSaved);
outstate.putInt("stateData2", someIntegerToBeSaved);
...
} //onSavedInstanceState

Operations on Fragments

FragmentTransaction

• add()

<FrameLayout>

<LinearLayout>
<LinearLayout>

• remove()
BackStack
• replace()
• show() / hide()
• attach() / detach()
redFragment <FrameLayout> main_ui_holder.

FragmentTransaction ft = getFragmentManager().beginTransaction();

redFragment = FragmentRed.newInstance(intValue);
ft.replace(R.id.main_ui_holder, redFragment, "RED-TAG"); //fragment's view is displayed
//destroying previous fragment (if any!)

ft.add(R.id.main_ui_holder, redFragment, "RED-TAG"); //fragment's view overlaps UI

ft.hide(redFragment); //fragment's view becomes invisible


ft.show(redFragment); //fragment's view is displayed

ft.detach(redFragment); //fragment's view is removed from UI (not destroyed)


ft.attach(redFragment); //fragment's view is displayed

ft.commit();

// find out what fragment is currently shown inside a given UI container


Fragment currentGuest = (Fragment)getFragmentManager().findFragmentById(R.id.main_holder);

Using the BackStack to Recreate State

BackStack
FragmentTransactions)

Back

BackStack
Back BackStack
BackStack

BackStack

BackStack
BackStack

BackStack

FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment redFragment = FragmentRed.newInstance(intParameterValue);
ft.replace(R.id.main_ui_holder, redFragment, "RED-FRAG1");
ft.addToBackStack("FRAGTRAN-RED1");
ft.commit();

FragmentTransaction ft
FragmentRed . "RED-FRAG1"

main_ui_holder "RED-FRAG1"

Fragment fragmentInstance = (Fragment)getFragmentManager().findFragmentById(R.id.ui_home)

ft.addToBackStack("FRAGTRAN-RED1");

BackStack
FRAGTRAN-RED1
BackStack BackStack
"FRAGTRAN-RED1"

BackStack

• .popBackStackImmediate(id,flag) BackStack
id
"FRAGTRAN-RED1" flag
FragmentManager.POP_BACK_STACK_INCLUSIVE.

// Remove current fragment’s UI and show its immediate predecessor


try {
FragmentTransaction ft = getFragmentManager().beginTransaction();
FragmentManager fragmentManager = getFragmentManager();
// find out how many entries are there in the BackStack
int bsCount = fragmentManager.getBackStackEntryCount();
// NOTE: bottom of the stack is at location 0, while its top is at position (bsCount – 1)
// obtain the id and tag of the BackStack's top (last) entry
String tag = fragmentManager.getBackStackEntryAt(bsCount-1).getName();
int id = fragmentManager.getBackStackEntryAt(bsCount-1).getId();
// use reference to remove fragments up to matching id (inclusive), expose previous (if any!)
fragmentManager.popBackStackImmediate(id, FragmentManager.POP_BACK_STACK_INCLUSIVE);
ft.commit();

} catch (Exception e) {
Log.e("ERROR-REMOVING-BS>>> ", e.getMessage() );
}

Back
BackStack getBackStackEntryCount()
bsCount. tag id
fragmentManager.getBackStackEntryAt(bsCount-1).getId().

.popBackStackImmediate(id,flag) BackStack
BackStack

POP_BACK_STACK_INCLUSIVE
BackStack Pop() Peek()

FragmentTransaction
BackStack "FTRAN0" "FTRAN1"

Back

try {
FragmentManager fragmentManager = getFragmentManager();
// VERSION 1: HIGH-ANCESTOR NAVIGATION (indexed as 0, 1, 2, ...)
// removes all BackStack entries up to given position, which is excluded from removal, and
// it is finally shown (remember that bottom of the BackStack is at position zero).
fragmentManager.popBackStackImmediate(0, 0);

// VERSION 2: Navigate back to a particular ancestor (Tagged here as 'FTRAN1')


fragmentManager.popBackStackImmediate("FTRAN1", FragmentManager.POP_BACK_STACK_INCLUSIVE);

} catch (Exception e) {
Log.e("HIGH-ANCESTOR>>>", "error: " + e.getMessage());
}

fragmentManager.popBackStackImmediate(0,0) BackStack

FragmentTransaction references BackStack


"FTRAN1" BackStack
FragmentManager.POP_BACK_STACK_INCLUSIVE. BackStack
"FTRAN0"
Example 6.4 BackStack Based Navigation

BackStack
BackStack

<?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:baselineAligned="false"
android:orientation="vertical"
android:gravity="center"
android:padding="10dp" >

<TextView
android:id="@+id/textView1Main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#77ffff00"
android:text="\nMain Layout ..."
android:textAppearance="?android:attr/textAppearanceLarge" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal" >

<Button
android:id="@+id/button1MainAddRed"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="ADD new RedFragment" />
<Button
android:id="@+id/button2MainPop"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="POP Trans BackStack" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal" >

<Button
android:id="@+id/button4MainReplace"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="REPLACE new RedFragment" />

<Button
android:id="@+id/button3MainRemove"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false"
android:text="FIND &amp; REMOVE TAG \n 'FRAGTRAN-RED2'" />
</LinearLayout>

<FrameLayout
android:id="@+id/main_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:orientation="vertical" />

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_red"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<TextView
android:id="@+id/textView1Red"
android:layout_width="match_parent"
android:layout_height="175dp"
android:layout_margin="20dp"
android:background="#d50000"
android:gravity="center"
android:text="Red Layout..."
android:textColor="@android:color/white"
android:textSize="35sp"
android:textStyle="bold" />

<Button
android:id="@+id/button1Red"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:text="Change Red Label" />

</LinearLayout>

package csu.matos;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements IMainCallbacks, View.OnClickListener {

FragmentTransaction ft;
FragmentRed redFragment;
TextView txtMsg;
Button btnAddRedFragment;
Button btnReplaceRedFragment;
Button btnPop;
Button btnRemove;
int serialCounter = 0; //used to enumerate fragments
String redMessage;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// plumbing TextView and Buttons held in main layout
txtMsg = (TextView) findViewById(R.id.textView1Main);
//buttons
btnAddRedFragment = (Button) findViewById(R.id.button1MainAddRed);
btnPop = (Button) findViewById(R.id.button2MainPop);
btnRemove = (Button) findViewById(R.id.button3MainRemove);
btnReplaceRedFragment = (Button) findViewById(R.id.button4MainReplace);
btnAddRedFragment.setOnClickListener(this);
btnPop.setOnClickListener(this);
btnRemove.setOnClickListener(this);
btnReplaceRedFragment.setOnClickListener(this);

// CallBack method (receiving messages coming from Fragments)


@Override
public void onMsgFromFragToMain(String sender, String strValue) {
// show message arriving to MainActivity
txtMsg.setText( sender + "=>" + strValue );
}

// reacting to button's click events


public void onClick(View v) {
// ADD
if(v.getId() == btnAddRedFragment.getId() ){
addRedFragment(++serialCounter);
btnRemove.setEnabled(true);
//WhatFragmentIsSittingInsideUIRegion(); // try - for debugging purposes!

}
// REPLACE
// should not be mixed with .add fragment
if(v.getId() == btnReplaceRedFragment.getId() ){
replaceRedFragment(++serialCounter);
btnRemove.setEnabled(true);
}

// POP (come back to previous UI - if any!)


if(v.getId() == btnPop.getId() ){
FragmentManager fragmentManager = getFragmentManager();
int bsCount = fragmentManager.getBackStackEntryCount();
txtMsg.setText("\nBACKSTACK old size=" + bsCount);

if(bsCount>0) {
// popBackStack removes a Transaction from the BackStack, its view is also deleted
String tag = fragmentManager.getBackStackEntryAt(bsCount-1).getName();
int id = fragmentManager.getBackStackEntryAt(bsCount-1).getId();
Log.e(bsCount +"POPPING-1 (GONE): ", "TAG=" + tag + " ID=" + id);

// execute POP operation


fragmentManager.popBackStackImmediate(id, FragmentManager.POP_BACK_STACK_INCLUSIVE);
//fragmentManager.popBackStackImmediate(id, 0); //try - doesn't remove stack top

// complete any pending insertions in the BackStack, then report its size
getFragmentManager().executePendingTransactions();
bsCount = fragmentManager.getBackStackEntryCount();

//spying: the current stack top is...


spyStackTop("POPPING-2 (TOP): ");

txtMsg.append("\nBACKSTACK new size=" + fragmentManager.getBackStackEntryCount() );


}

}//Pop

// REMOVE
if(v.getId() == btnRemove.getId() ){
txtMsg.setText("Removing...");

try {

FragmentManager fragmentManager = getFragmentManager();


int bsCount = fragmentManager.getBackStackEntryCount();
txtMsg.setText("BACKSTACK old size=" + bsCount);

// VERSION 1: HIGH-ANCESTOR NAVIGATION (indexed as 0, 1, 2, ...)


// removes all BackStack entries up to given position (excluded).
// remember that bottom of the BackStack is at position zero.
fragmentManager.popBackStackImmediate(0, 0);

// VERSION 2: Navigate back to a particular ancestor (Tagged as 'FRAGTRAN-RED2')


// ----------------------------------------------------------------------------
//fragmentManager.popBackStackImmediate("FRAGTRAN-RED2",
// FragmentManager.POP_BACK_STACK_INCLUSIVE);

// EXTRA: TRY - CLEARING BACKSTACK


//fragmentManager.popBackStackImmediate(null,
// FragmentManager.POP_BACK_STACK_INCLUSIVE);
//Log.e("REMOVING>","1BACKSTACK new size=" +
// fragmentManager.getBackStackEntryCount() );

// complete any pending insertions in the BackStack, then report its size
fragmentManager.executePendingTransactions();
Log.e("REMOVING>","2BACKSTACK new size=" + fragmentManager.getBackStackEntryCount());

txtMsg.append("\nBACKSTACK new size=" + fragmentManager.getBackStackEntryCount());


} catch (Exception e) {
Log.e("REMOVING>", "Error: " + e.getMessage());
}

}//Remove

}//onClick

// user pushes the device's "BACK" button


@Override
public void onBackPressed() {
super.onBackPressed();
int counter = getFragmentManager().getBackStackEntryCount();
txtMsg.setText("BACKSTACK size=" + counter);
}

public void addRedFragment(int intValue) {


// create a new RED fragment, add fragment to the transaction
FragmentTransaction ft = getFragmentManager().beginTransaction();
redFragment = FragmentRed.newInstance(intValue);
// add the fragment to the UI
ft.add(R.id.main_holder, redFragment, "RED-TAG" + intValue);
// push reference to fragment-transaction on top of the BACKSTACK
ft.addToBackStack("FRAGTRAN-RED" + intValue);
ft.commit();

// complete any pending insertions in the BackStack, then report its size
getFragmentManager().executePendingTransactions();
txtMsg.setText("\nBACKSTACK size =" + getFragmentManager().getBackStackEntryCount() );

spyStackTop("SPYING TOP AFTER ADDING ");


}

public void replaceRedFragment(int intValue) {


// create a new RED fragment, replace fragments in the transaction
FragmentTransaction ft = getFragmentManager().beginTransaction();
redFragment = FragmentRed.newInstance(intValue);

ft.replace(R.id.main_holder, redFragment, "RED-TAG" + intValue);

ft.addToBackStack("FRAGTRAN-RED" + intValue);
ft.commit();
// complete any pending insertions in the BackStack, then report its size
getFragmentManager().executePendingTransactions();
txtMsg.setText("BACKSTACK size =" + getFragmentManager().getBackStackEntryCount() );
spyStackTop("AFTER REPLACE ");
}

private void spyStackTop(String callerIdMsg){


// show TAG and ID of top BACKSTACK entry together with callerIdMsg
FragmentManager fragmentManager = getFragmentManager();
int bsCount = fragmentManager.getBackStackEntryCount();

if(bsCount>0) {
String tag = fragmentManager.getBackStackEntryAt(bsCount-1).getName();
int id = fragmentManager.getBackStackEntryAt(bsCount-1).getId();
Log.e( "BACKSTACK-" + bsCount + " " + callerIdMsg, ">>> TAG=" + tag + " ID=" + id);
}
}

public void showBackStack(){


try {
FragmentTransaction ft = getFragmentManager().beginTransaction();
android.app.FragmentManager fragmentManager = getFragmentManager();
for (int bsCount = fragmentManager.getBackStackEntryCount();
bsCount >= 1; bsCount--) {
String tag = fragmentManager.getBackStackEntryAt(bsCount-1).getName();
int id = fragmentManager.getBackStackEntryAt(bsCount-1).getId();
Log.e(bsCount +"ShowBackStack: ", "" + tag + " " + id);
}
ft.commit();
} catch (Exception e) {
Log.e("ShowBackStack-Error>>> ", e.getMessage() );
}

private Fragment whatFragmentIsSittingInsideUIRegion(){


//tell the TAG and ID of fragment in given UI region
try {
Fragment fragmentInstance = getFragmentManager().findFragmentById(R.id.main_holder);
if (fragmentInstance != null){
String tag = fragmentInstance.getTag();
int id = fragmentInstance.getId();
Log.e("UTILITY >>> ", "TAG: " + tag + " ID:" + id);
}
return fragmentInstance;
} catch (Exception e) {
Log.e("ERROR-UTILITY>>> ", e.getMessage() );
return null;
}
}
}

 Add New Fragment


Change Red Label
FragmentTransaction
add() addRedFragment()
FrameLayout
BackStack FRAGTRAN-RED1
FRAGTRAN-RED2

Pop Trans BackStack

Pop

BackStack
Find & Remove FRAGTRAN-RED2
BackStack
BackStack

 Replace New Fragment Add New


RedFragment replace()
BackStack

pop BackStack
WARNING
.add() .replace()

public class FragmentRed extends Fragment {


MainActivity main;
TextView txtRed;
Button btnRedClock;
int fragmentId;
String selectedRedText = "";

public static FragmentRed newInstance(int fragmentId) {


FragmentRed fragment = new FragmentRed();
Bundle bundle = new Bundle();
bundle.putInt("fragmentId", fragmentId);
fragment.setArguments(bundle);
return fragment;
}// newInstance

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

// Activities containing this fragment must implement MainCallbacks


if (!(getActivity() instanceof IMainCallbacks)) {
throw new IllegalStateException(
">>> Activity must implement IMainCallbacks");
}
main = (MainActivity) getActivity();
fragmentId = getArguments().getInt("fragmentId", -1);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

LinearLayout view_layout_red = (LinearLayout) inflater.inflate(


R.layout.layout_red, null);

txtRed = (TextView) view_layout_red.findViewById(R.id.textView1Red);


txtRed.setText( "Fragment " + fragmentId );

btnRedClock = (Button) view_layout_red.findViewById(R.id.button1Red);


btnRedClock.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
selectedRedText = "\nRed Clock:\n" + new Date().toString();
txtRed.append(selectedRedText);
// main.onMsgFromFragToMain("RED-FRAG", selectedRedText );
}
});
return view_layout_red;
}

}// FragmentRed

FragmentTransaction
BackStack Change Red Label

// method to pass messages from fragments to MainActivity


// it must be implemented by the Host Activity

public interface IMainCallbacks {


public void onMsgFromFragToMain ( String sender, String strValue);

}
MainActivity
sender strValue MainActivity

You might also like