Beruflich Dokumente
Kultur Dokumente
Fragments
Goals
1 2 3 4 5 6 7 8 9 10 11
onAttach onCreate onCreateView onACtivityCreated onStart onResume onPause onStop onDestroyView onDestroy onDetach
•
•
•
•
<fragment>
android:name=fragmentName
Dynamic Binding
FragmentTransaction
add()
replace()
FragmentManager
FragmentTransaction ft= getFragmentManager().beginTransaction();
ft.replace(R.id.main_holder_blue, blueFragment);
ft.commit();
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.Fragment;
TextView
TextView
MainActivity FragmentBlue FragmentRed
IFragmentCallbacks IMainCallbacks
MainActivity MainActivity
activity_main.xml layout_blue.xml layout_red
<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>
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);
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 ...
@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) {
// 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 ...
@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);
@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 MainActivity
onMsgFromMainToFragment
blueFragment
MainActivity FragmentRed
FragmentBlue
layout_red.xml layout_blue.xml
•
<fragment>
1. android:name="AppPackageName.FragmentClassName"
2. android:id="@id+/uniqueName"
3. android:tag="string"
<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;
}
}
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());
}
}
onCreate() onCreateView()
android:name="csu.matos.FragmentXYZ"
onAttachFragment
redFragment blueFragment
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
@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);
@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
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@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);
@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;
}
}
onSaveInstanceState
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
...
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.commit();
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"
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.
} 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);
} catch (Exception e) {
Log.e("HIGH-ANCESTOR>>>", "error: " + e.getMessage());
}
fragmentManager.popBackStackImmediate(0,0) BackStack
BackStack
BackStack
<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 & 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;
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);
}
// REPLACE
// should not be mixed with .add fragment
if(v.getId() == btnReplaceRedFragment.getId() ){
replaceRedFragment(++serialCounter);
btnRemove.setEnabled(true);
}
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);
// complete any pending insertions in the BackStack, then report its size
getFragmentManager().executePendingTransactions();
bsCount = fragmentManager.getBackStackEntryCount();
}//Pop
// REMOVE
if(v.getId() == btnRemove.getId() ){
txtMsg.setText("Removing...");
try {
// complete any pending insertions in the BackStack, then report its size
fragmentManager.executePendingTransactions();
Log.e("REMOVING>","2BACKSTACK new size=" + fragmentManager.getBackStackEntryCount());
}//Remove
}//onClick
// complete any pending insertions in the BackStack, then report its size
getFragmentManager().executePendingTransactions();
txtMsg.setText("\nBACKSTACK size =" + getFragmentManager().getBackStackEntryCount() );
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 ");
}
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);
}
}
Pop
BackStack
Find & Remove FRAGTRAN-RED2
BackStack
BackStack
pop BackStack
WARNING
.add() .replace()
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@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
}
MainActivity
sender strValue MainActivity