More fragment work:
- Introduce FragmentManager as a public API, deprecating the fragment
APIs on Activity. (They will be removed soon.)
- Add APIs to write a fragment reference to a bundle and later retrieve
it.
- Add Fragment API to set another fragment as its target, for delivering
results.
- Change when onInflate() is called and formalize its meaning in relation
to the fragment arguments that were previously introduced.
- Change onDestroyView() to always be called, regardless of when
onCreateView() returns. It now also is called slightly differently,
after the view hierarchy's state is saved.
- Fix some issues with DialogFragment's lifecycle with its associated
Dialog and state save/restore.
- Preference can now have a Bundle associated with it to provide
arguments to a fragment. The data for this Bundle call be supplied
via <extra> tags under a PreferenceScreen.
- PreferenceActivity's header XML tags are now <preference-headers>
and <header>, and you can supply <extra> tags under a <header> to set
arguments for the header's fragment.
Change-Id: I22c212c9fa862d50840201ca16e51f9de5ef0031
diff --git a/api/current.xml b/api/current.xml
index d35037e..4356852 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -21796,7 +21796,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<parameter name="id" type="int">
@@ -21809,7 +21809,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<parameter name="tag" type="java.lang.String">
@@ -23006,7 +23006,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</method>
@@ -23043,7 +23043,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</method>
@@ -23054,7 +23054,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<parameter name="name" type="java.lang.String">
@@ -23069,7 +23069,7 @@
synchronized="false"
static="false"
final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
<parameter name="id" type="int">
@@ -27856,6 +27856,28 @@
visibility="public"
>
</method>
+<method name="getTargetFragment"
+ return="android.app.Fragment"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getTargetRequestCode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getView"
return="android.view.View"
abstract="false"
@@ -28158,8 +28180,6 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="activity" type="android.app.Activity">
-</parameter>
<parameter name="attrs" type="android.util.AttributeSet">
</parameter>
<parameter name="savedInstanceState" type="android.os.Bundle">
@@ -28291,7 +28311,7 @@
native="false"
synchronized="false"
static="false"
- final="true"
+ final="false"
deprecated="not deprecated"
visibility="public"
>
@@ -28324,6 +28344,21 @@
<parameter name="retain" type="boolean">
</parameter>
</method>
+<method name="setTargetFragment"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragment" type="android.app.Fragment">
+</parameter>
+<parameter name="requestCode" type="int">
+</parameter>
+</method>
<method name="startActivity"
return="void"
abstract="false"
@@ -137652,6 +137687,17 @@
visibility="public"
>
</method>
+<method name="getExtras"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getFragment"
return="java.lang.String"
abstract="false"
@@ -138095,6 +138141,17 @@
<parameter name="defaultValue" type="java.lang.Object">
</parameter>
</method>
+<method name="peekExtras"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="persistBoolean"
return="boolean"
abstract="false"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ec3cbc3..d40d7d8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1590,7 +1590,9 @@
/**
* Start a series of edit operations on the Fragments associated with
* this activity.
+ * @deprecated use {@link #getFragmentManager}.
*/
+ @Deprecated
public FragmentTransaction openFragmentTransaction() {
return mFragments.openTransaction();
}
@@ -1782,7 +1784,9 @@
* from XML or as the container ID when added in a transaction. This only
* returns fragments that are currently added to the activity's content.
* @return The fragment if found or null otherwise.
+ * @deprecated use {@link #getFragmentManager}.
*/
+ @Deprecated
public Fragment findFragmentById(int id) {
return mFragments.findFragmentById(id);
}
@@ -1792,7 +1796,9 @@
* from XML or as supplied when added in a transaction. This only
* returns fragments that are currently added to the activity's content.
* @return The fragment if found or null otherwise.
+ * @deprecated use {@link #getFragmentManager}.
*/
+ @Deprecated
public Fragment findFragmentByTag(String tag) {
return mFragments.findFragmentByTag(tag);
}
@@ -2078,7 +2084,9 @@
/**
* Pop the top state off the back stack. Returns true if there was one
* to pop, else false.
+ * @deprecated use {@link #getFragmentManager}.
*/
+ @Deprecated
public boolean popBackStack() {
return mFragments.popBackStack();
}
@@ -2091,7 +2099,9 @@
* {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether
* the named state itself is popped. If null, only the top state is popped.
* @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
+ * @deprecated use {@link #getFragmentManager}.
*/
+ @Deprecated
public boolean popBackStack(String name, int flags) {
return mFragments.popBackStack(name, flags);
}
@@ -2105,7 +2115,9 @@
* {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether
* the named state itself is popped.
* @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}.
+ * @deprecated use {@link #getFragmentManager}.
*/
+ @Deprecated
public boolean popBackStack(int id, int flags) {
return mFragments.popBackStack(id, flags);
}
@@ -2116,7 +2128,7 @@
* but you can override this to do whatever you want.
*/
public void onBackPressed() {
- if (!popBackStack()) {
+ if (!mFragments.popBackStack()) {
finish();
}
}
@@ -3995,9 +4007,12 @@
return null;
}
+ String fname = attrs.getAttributeValue(null, "class");
TypedArray a =
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment);
- String fname = a.getString(com.android.internal.R.styleable.Fragment_name);
+ if (fname == null) {
+ fname = a.getString(com.android.internal.R.styleable.Fragment_name);
+ }
int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, 0);
String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
a.recycle();
@@ -4020,14 +4035,14 @@
fragment.mFragmentId = id;
fragment.mTag = tag;
fragment.mImmediateActivity = this;
+ // If this fragment is newly instantiated (either right now, or
+ // from last saved state), then give it the attributes to
+ // initialize itself.
+ if (!fragment.mRetaining) {
+ fragment.onInflate(attrs, fragment.mSavedFragmentState);
+ }
mFragments.addFragment(fragment, true);
}
- // If this fragment is newly instantiated (either right now, or
- // from last saved state), then give it the attributes to
- // initialize itself.
- if (!fragment.mRetaining) {
- fragment.onInflate(this, attrs, fragment.mSavedFragmentState);
- }
if (fragment.mView == null) {
throw new IllegalStateException("Fragment " + fname
+ " did not create a view.");
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index 3124f0d..50e7421 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -79,6 +79,7 @@
Dialog mDialog;
boolean mDestroyed;
+ boolean mRemoved;
public DialogFragment() {
}
@@ -136,6 +137,7 @@
*/
public int show(Activity activity, FragmentTransaction transaction, String tag) {
transaction.add(this, tag);
+ mRemoved = false;
mBackStackId = transaction.commit();
return mBackStackId;
}
@@ -149,12 +151,15 @@
public void dismiss() {
if (mDialog != null) {
mDialog.dismiss();
+ mDialog = null;
}
+ mRemoved = true;
if (mBackStackId >= 0) {
- getActivity().popBackStack(mBackStackId, Activity.POP_BACK_STACK_INCLUSIVE);
+ getFragmentManager().popBackStack(mBackStackId,
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
mBackStackId = -1;
} else {
- FragmentTransaction ft = getActivity().openFragmentTransaction();
+ FragmentTransaction ft = getFragmentManager().openTransaction();
ft.remove(this);
ft.commit();
}
@@ -193,15 +198,12 @@
}
public void onCancel(DialogInterface dialog) {
- if (mBackStackId >= 0) {
- // If this fragment is part of the back stack, then cancelling
- // the dialog means popping off the back stack.
- getActivity().popBackStack(mBackStackId, Activity.POP_BACK_STACK_INCLUSIVE);
- mBackStackId = -1;
- }
}
public void onDismiss(DialogInterface dialog) {
+ if (!mRemoved) {
+ dismiss();
+ }
}
@Override
@@ -241,7 +243,10 @@
@Override
public void onStart() {
super.onStart();
- mDialog.show();
+ if (mDialog != null) {
+ mRemoved = false;
+ mDialog.show();
+ }
}
@Override
@@ -262,17 +267,25 @@
@Override
public void onStop() {
super.onStop();
- mDialog.hide();
+ if (mDialog != null) {
+ mDialog.hide();
+ }
}
/**
- * Detach from list view.
+ * Remove dialog.
*/
@Override
public void onDestroyView() {
super.onDestroyView();
mDestroyed = true;
- mDialog.dismiss();
- mDialog = null;
+ if (mDialog != null) {
+ // Set removed here because this dismissal is just to hide
+ // the dialog -- we don't want this to cause the fragment to
+ // actually be removed.
+ mRemoved = true;
+ mDialog.dismiss();
+ mDialog = null;
+ }
}
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index bc839d7..9a1db96 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -42,8 +42,6 @@
import java.util.HashMap;
final class FragmentState implements Parcelable {
- static final String VIEW_STATE_TAG = "android:view_state";
-
final String mClassName;
final int mIndex;
final boolean mFromLayout;
@@ -90,8 +88,6 @@
if (mSavedFragmentState != null) {
mSavedFragmentState.setClassLoader(activity.getClassLoader());
mInstance.mSavedFragmentState = mSavedFragmentState;
- mInstance.mSavedViewState
- = mSavedFragmentState.getSparseParcelableArray(VIEW_STATE_TAG);
}
mInstance.setIndex(mIndex);
mInstance.mFromLayout = mFromLayout;
@@ -160,6 +156,12 @@
// Construction arguments;
Bundle mArguments;
+ // Target fragment.
+ Fragment mTarget;
+
+ // Target request code.
+ int mTargetRequestCode;
+
// True if the fragment is in the list of added fragments.
boolean mAdded;
@@ -375,7 +377,7 @@
* arguments supplied here will be retained across fragment destroy and
* creation.
*/
- final public void setArguments(Bundle args) {
+ public void setArguments(Bundle args) {
if (mIndex >= 0) {
throw new IllegalStateException("Fragment already active");
}
@@ -391,6 +393,36 @@
}
/**
+ * Optional target for this fragment. This may be used, for example,
+ * if this fragment is being started by another, and when done wants to
+ * give a result back to the first. The target set here is retained
+ * across instances via {@link FragmentManager#putFragment
+ * FragmentManager.putFragment()}.
+ *
+ * @param fragment The fragment that is the target of this one.
+ * @param requestCode Optional request code, for convenience if you
+ * are going to call back with {@link #onActivityResult(int, int, Intent)}.
+ */
+ public void setTargetFragment(Fragment fragment, int requestCode) {
+ mTarget = fragment;
+ mTargetRequestCode = requestCode;
+ }
+
+ /**
+ * Return the target fragment set by {@link #setTargetFragment(Fragment)}.
+ */
+ final public Fragment getTargetFragment() {
+ return mTarget;
+ }
+
+ /**
+ * Return the target request code set by {@link #setTargetFragment(Fragment)}.
+ */
+ final public int getTargetRequestCode() {
+ return mTargetRequestCode;
+ }
+
+ /**
* Return the Activity this fragment is currently associated with.
*/
final public Activity getActivity() {
@@ -537,21 +569,30 @@
/**
* Called when a fragment is being created as part of a view layout
* inflation, typically from setting the content view of an activity. This
- * will be called both the first time the fragment is created, as well
- * later when it is being re-created from its saved state (which is also
- * given here).
+ * will be called immediately after the fragment is created from a <fragment>
+ * tag in a layout file. Note this is <em>before</em> the fragment's
+ * {@link #onAttach(Activity)} has been called; all you should do here is
+ * parse the attributes and save them away. A convenient thing to do is
+ * simply copy them into a Bundle that is given to {@link #setArguments(Bundle)}.
*
- * XXX This is kind-of yucky... maybe we could just supply the
- * AttributeSet to onCreate()?
+ * <p>This is called every time the fragment is inflated, even if it is
+ * being inflated into a new instance with saved state. Because a fragment's
+ * arguments are retained across instances, it may make no sense to re-parse
+ * the attributes into new arguments. You may want to first check
+ * {@link #getArguments()} and only parse the attributes if it returns null,
+ * the assumption being that if it is non-null those are the same arguments
+ * from the first time the fragment was inflated. (That said, you may want
+ * to have layouts change for different configurations such as landscape
+ * and portrait, which can have different attributes. If so, you will need
+ * to re-parse the attributes each time this is called to generate new
+ * arguments.)</p>
*
- * @param activity The Activity that is inflating the fragment.
* @param attrs The attributes at the tag where the fragment is
* being created.
* @param savedInstanceState If the fragment is being re-created from
* a previous saved state, this is the state.
*/
- public void onInflate(Activity activity, AttributeSet attrs,
- Bundle savedInstanceState) {
+ public void onInflate(AttributeSet attrs, Bundle savedInstanceState) {
mCalled = true;
}
@@ -693,8 +734,10 @@
* Called when the view previously created by {@link #onCreateView} has
* been detached from the fragment. The next time the fragment needs
* to be displayed, a new view will be created. This is called
- * after {@link #onStop()} and before {@link #onDestroy()}; it is only
- * called if {@link #onCreateView} returns a non-null View.
+ * after {@link #onStop()} and before {@link #onDestroy()}. It is called
+ * <em>regardless</em> of whether {@link #onCreateView} returned a
+ * non-null view. Internally it is called after the view's state has
+ * been saved but before it has been removed from its parent.
*/
public void onDestroyView() {
mCalled = true;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 0556f05..f190d0d 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -166,13 +166,16 @@
}
/**
- * @hide
* Container for fragments associated with an activity.
*/
-class FragmentManagerImpl implements FragmentManager {
+final class FragmentManagerImpl implements FragmentManager {
static final boolean DEBUG = true;
static final String TAG = "FragmentManager";
+ static final String TARGET_REQUEST_CODE_STATE_TAG = "android:target_req_state";
+ static final String TARGET_STATE_TAG = "android:target_state";
+ static final String VIEW_STATE_TAG = "android:view_state";
+
ArrayList<Runnable> mPendingActions;
Runnable[] mTmpActions;
boolean mExecutingActions;
@@ -201,7 +204,6 @@
execPendingActions();
}
};
-
public FragmentTransaction openTransaction() {
return new BackStackEntry(this);
}
@@ -230,7 +232,10 @@
}
public Fragment getFragment(Bundle bundle, String key) {
- int index = bundle.getInt(key);
+ int index = bundle.getInt(key, -1);
+ if (index == -1) {
+ return null;
+ }
if (index >= mActive.size()) {
throw new IllegalStateException("Fragement no longer exists for key "
+ key + ": index " + index);
@@ -296,6 +301,16 @@
switch (f.mState) {
case Fragment.INITIALIZING:
if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
+ if (f.mSavedFragmentState != null) {
+ f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
+ FragmentManagerImpl.VIEW_STATE_TAG);
+ f.mTarget = getFragment(f.mSavedFragmentState,
+ FragmentManagerImpl.TARGET_STATE_TAG);
+ if (f.mTarget != null) {
+ f.mTargetRequestCode = f.mSavedFragmentState.getInt(
+ FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
+ }
+ }
f.mActivity = mActivity;
f.mCalled = false;
f.onAttach(mActivity);
@@ -419,32 +434,32 @@
if (newState < Fragment.ACTIVITY_CREATED) {
if (DEBUG) Log.v(TAG, "movefrom CONTENT: " + f);
if (f.mView != null) {
- f.mCalled = false;
- f.onDestroyView();
- if (!f.mCalled) {
- throw new SuperNotCalledException("Fragment " + f
- + " did not call through to super.onDestroyedView()");
- }
// Need to save the current view state if not
// done already.
if (!mActivity.isFinishing() && f.mSavedFragmentState == null) {
saveFragmentViewState(f);
}
- if (f.mContainer != null) {
- if (mCurState > Fragment.INITIALIZING) {
- Animatable anim = loadAnimatable(f, transit, true,
- transitionStyle);
- if (anim != null) {
- if (anim instanceof Sequencer) {
- ((Sequencer)anim).setTarget(f.mView);
- } else if (anim instanceof PropertyAnimator) {
- ((PropertyAnimator)anim).setTarget(f.mView);
- }
- anim.start();
+ }
+ f.mCalled = false;
+ f.onDestroyView();
+ if (!f.mCalled) {
+ throw new SuperNotCalledException("Fragment " + f
+ + " did not call through to super.onDestroyedView()");
+ }
+ if (f.mView != null && f.mContainer != null) {
+ if (mCurState > Fragment.INITIALIZING) {
+ Animatable anim = loadAnimatable(f, transit, true,
+ transitionStyle);
+ if (anim != null) {
+ if (anim instanceof Sequencer) {
+ ((Sequencer)anim).setTarget(f.mView);
+ } else if (anim instanceof PropertyAnimator) {
+ ((PropertyAnimator)anim).setTarget(f.mView);
}
+ anim.start();
}
- f.mContainer.removeView(f.mView);
}
+ f.mContainer.removeView(f.mView);
}
f.mContainer = null;
f.mView = null;
@@ -908,7 +923,20 @@
fs.mSavedFragmentState = new Bundle();
}
fs.mSavedFragmentState.putSparseParcelableArray(
- FragmentState.VIEW_STATE_TAG, f.mSavedViewState);
+ FragmentManagerImpl.VIEW_STATE_TAG, f.mSavedViewState);
+ }
+ }
+
+ if (f.mTarget != null) {
+ if (fs.mSavedFragmentState == null) {
+ fs.mSavedFragmentState = new Bundle();
+ }
+ putFragment(fs.mSavedFragmentState,
+ FragmentManagerImpl.TARGET_STATE_TAG, f.mTarget);
+ if (f.mTargetRequestCode != 0) {
+ fs.mSavedFragmentState.putInt(
+ FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG,
+ f.mTargetRequestCode);
}
}
@@ -976,7 +1004,7 @@
f.mAdded = false;
if (fs.mSavedFragmentState != null) {
f.mSavedViewState = fs.mSavedFragmentState.getSparseParcelableArray(
- FragmentState.VIEW_STATE_TAG);
+ FragmentManagerImpl.VIEW_STATE_TAG);
}
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 812af5a..9b23c1e 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1559,7 +1559,7 @@
/**
* Parse a series of {@link android.R.styleable#Extra <extra>} tags from
* an XML file. You call this when you are at the parent tag of the
- * extra tags, and it return once all of the child tags have been parsed.
+ * extra tags, and it will return once all of the child tags have been parsed.
* This will call {@link #parseBundleExtra} for each extra tag encountered.
*
* @param parser The parser from which to retrieve the extras.
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 117e507..ffc2862 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -90,6 +90,7 @@
private String mKey;
private Intent mIntent;
private String mFragment;
+ private Bundle mExtras;
private boolean mEnabled = true;
private boolean mSelectable = true;
private boolean mRequiresKey;
@@ -339,6 +340,26 @@
}
/**
+ * Return the extras Bundle object associated with this preference, creating
+ * a new Bundle if there currently isn't one. You can use this to get and
+ * set individual extra key/value pairs.
+ */
+ public Bundle getExtras() {
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ return mExtras;
+ }
+
+ /**
+ * Return the extras Bundle object associated with this preference,
+ * returning null if there is not currently one.
+ */
+ public Bundle peekExtras() {
+ return mExtras;
+ }
+
+ /**
* Sets the layout resource that is inflated as the {@link View} to be shown
* for this Preference. In most cases, the default layout is sufficient for
* custom Preference objects and only the widget layout needs to be changed.
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 32bf170..6b00690 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -313,7 +313,7 @@
setListAdapter(mAdapter);
if (!mSinglePane) {
mPrefsContainer.setVisibility(View.VISIBLE);
- if (initialFragment != null) {
+ if (initialFragment == null) {
Header h = onGetInitialHeader();
initialFragment = h.fragment;
initialArguments = h.fragmentArguments;
@@ -464,12 +464,14 @@
}
String nodeName = parser.getName();
- if (!"PreferenceHeaders".equals(nodeName)) {
+ if (!"preference-headers".equals(nodeName)) {
throw new RuntimeException(
- "XML document must start with <PreferenceHeaders> tag; found"
+ "XML document must start with <preference-headers> tag; found"
+ nodeName + " at " + parser.getPositionDescription());
}
+ Bundle curBundle = null;
+
int outerDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -478,7 +480,7 @@
}
nodeName = parser.getName();
- if ("Header".equals(nodeName)) {
+ if ("header".equals(nodeName)) {
Header header = new Header();
TypedArray sa = getResources().obtainAttributes(attrs,
@@ -493,9 +495,16 @@
com.android.internal.R.styleable.PreferenceHeader_fragment);
sa.recycle();
- target.add(header);
+ if (curBundle == null) {
+ curBundle = new Bundle();
+ }
+ getResources().parseBundleExtras(parser, curBundle);
+ if (curBundle.size() > 0) {
+ header.fragmentArguments = curBundle;
+ curBundle = null;
+ }
- XmlUtils.skipCurrentTag(parser);
+ target.add(header);
} else {
XmlUtils.skipCurrentTag(parser);
}
@@ -631,16 +640,17 @@
* @param args Optional arguments to supply to the fragment.
*/
public void switchToHeader(String fragmentName, Bundle args) {
- popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
+ getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
Fragment f = Fragment.instantiate(this, fragmentName, args);
- openFragmentTransaction().replace(com.android.internal.R.id.prefs, f).commit();
+ getFragmentManager().openTransaction().replace(
+ com.android.internal.R.id.prefs, f).commit();
}
@Override
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
- Fragment f = Fragment.instantiate(this, pref.getFragment());
- openFragmentTransaction().replace(com.android.internal.R.id.prefs, f)
+ Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras());
+ getFragmentManager().openTransaction().replace(com.android.internal.R.id.prefs, f)
.addToBackStack(BACK_STACK_PREFS).commit();
return true;
}
diff --git a/core/java/android/preference/PreferenceInflater.java b/core/java/android/preference/PreferenceInflater.java
index 779e746..c21aa18 100644
--- a/core/java/android/preference/PreferenceInflater.java
+++ b/core/java/android/preference/PreferenceInflater.java
@@ -16,6 +16,8 @@
package android.preference;
+import com.android.internal.util.XmlUtils;
+
import java.io.IOException;
import java.util.Map;
@@ -39,6 +41,7 @@
class PreferenceInflater extends GenericInflater<Preference, PreferenceGroup> {
private static final String TAG = "PreferenceInflater";
private static final String INTENT_TAG_NAME = "intent";
+ private static final String EXTRA_TAG_NAME = "extra";
private PreferenceManager mPreferenceManager;
@@ -73,8 +76,10 @@
try {
intent = Intent.parseIntent(getContext().getResources(), parser, attrs);
} catch (IOException e) {
- Log.w(TAG, "Could not parse Intent.");
- Log.w(TAG, e);
+ XmlPullParserException ex = new XmlPullParserException(
+ "Error parsing preference");
+ ex.initCause(e);
+ throw ex;
}
if (intent != null) {
@@ -82,6 +87,18 @@
}
return true;
+ } else if (tag.equals(EXTRA_TAG_NAME)) {
+ getContext().getResources().parseBundleExtra(EXTRA_TAG_NAME, attrs,
+ parentPreference.getExtras());
+ try {
+ XmlUtils.skipCurrentTag(parser);
+ } catch (IOException e) {
+ XmlPullParserException ex = new XmlPullParserException(
+ "Error parsing preference");
+ ex.initCause(e);
+ throw ex;
+ }
+ return true;
}
return false;