summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml367
-rw-r--r--core/java/android/app/BackStackRecord.java (renamed from core/java/android/app/BackStackEntry.java)169
-rw-r--r--core/java/android/app/FragmentBreadCrumbs.java175
-rw-r--r--core/java/android/app/FragmentManager.java130
-rw-r--r--core/java/android/app/FragmentTransaction.java53
-rw-r--r--core/java/android/preference/PreferenceActivity.java90
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/res/res/color/primary_text_dark.xml3
-rw-r--r--core/res/res/color/primary_text_dark_focused.xml1
-rw-r--r--core/res/res/color/primary_text_dark_nodisable.xml1
-rw-r--r--core/res/res/color/primary_text_light.xml1
-rw-r--r--core/res/res/color/primary_text_light_nodisable.xml1
-rw-r--r--core/res/res/color/secondary_text_dark.xml1
-rw-r--r--core/res/res/color/secondary_text_dark_nodisable.xml1
-rw-r--r--core/res/res/color/secondary_text_light.xml1
-rw-r--r--core/res/res/color/secondary_text_light_nodisable.xml1
-rw-r--r--core/res/res/drawable-hdpi/nav_divider.pngbin0 -> 1012 bytes
-rw-r--r--core/res/res/drawable-mdpi/nav_divider.pngbin0 -> 2846 bytes
-rw-r--r--core/res/res/layout-port/preference_header_item.xml62
-rw-r--r--core/res/res/layout/fragment_bread_crumb_item.xml26
-rw-r--r--core/res/res/layout/fragment_bread_crumbs.xml22
-rw-r--r--core/res/res/layout/preference_header_item.xml1
-rw-r--r--core/res/res/layout/preference_list_content.xml4
-rwxr-xr-xcore/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/public.xml3
-rw-r--r--core/res/res/values/styles.xml5
26 files changed, 1038 insertions, 86 deletions
diff --git a/api/current.xml b/api/current.xml
index 279744e..ccd1724 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2792,6 +2792,28 @@
visibility="public"
>
</field>
+<field name="breadCrumbShortTitle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843589"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="breadCrumbTitle"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843588"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="bufferType"
type="int"
transient="false"
@@ -17384,6 +17406,17 @@
visibility="public"
>
</field>
+<field name="Widget_FragmentBreadCrumbs"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973986"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="Widget_Gallery"
type="int"
transient="false"
@@ -29343,6 +29376,113 @@
</parameter>
</constructor>
</class>
+<class name="FragmentBreadCrumbs"
+ extends="android.view.ViewGroup"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.app.FragmentManager.OnBackStackChangedListener">
+</implements>
+<constructor name="FragmentBreadCrumbs"
+ type="android.app.FragmentBreadCrumbs"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="FragmentBreadCrumbs"
+ type="android.app.FragmentBreadCrumbs"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="FragmentBreadCrumbs"
+ type="android.app.FragmentBreadCrumbs"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="onBackStackChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onLayout"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="changed" type="boolean">
+</parameter>
+<parameter name="l" type="int">
+</parameter>
+<parameter name="t" type="int">
+</parameter>
+<parameter name="r" type="int">
+</parameter>
+<parameter name="b" type="int">
+</parameter>
+</method>
+<method name="setActivity"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="a" type="android.app.Activity">
+</parameter>
+</method>
+<method name="setTitle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+<parameter name="shortTitle" type="java.lang.CharSequence">
+</parameter>
+</method>
+</class>
<interface name="FragmentManager"
abstract="true"
static="false"
@@ -29350,6 +29490,30 @@
deprecated="not deprecated"
visibility="public"
>
+<method name="addOnBackStackChangedListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener">
+</parameter>
+</method>
+<method name="countBackStackEntries"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="findFragmentById"
return="android.app.Fragment"
abstract="true"
@@ -29376,6 +29540,19 @@
<parameter name="tag" type="java.lang.String">
</parameter>
</method>
+<method name="getBackStackEntry"
+ return="android.app.FragmentManager.BackStackEntry"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+</method>
<method name="getFragment"
return="android.app.Fragment"
abstract="true"
@@ -29460,6 +29637,19 @@
<parameter name="fragment" type="android.app.Fragment">
</parameter>
</method>
+<method name="removeOnBackStackChangedListener"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.app.FragmentManager.OnBackStackChangedListener">
+</parameter>
+</method>
<field name="POP_BACK_STACK_INCLUSIVE"
type="int"
transient="false"
@@ -29472,6 +29662,66 @@
>
</field>
</interface>
+<interface name="FragmentManager.BackStackEntry"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getBreadCrumbShortTitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBreadCrumbTitle"
+ return="java.lang.CharSequence"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getId"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
+<interface name="FragmentManager.OnBackStackChangedListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onBackStackChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</interface>
<interface name="FragmentTransaction"
abstract="true"
static="false"
@@ -29619,6 +29869,58 @@
<parameter name="tag" type="java.lang.String">
</parameter>
</method>
+<method name="setBreadCrumbShortTitle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="int">
+</parameter>
+</method>
+<method name="setBreadCrumbShortTitle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setBreadCrumbTitle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="int">
+</parameter>
+</method>
+<method name="setBreadCrumbTitle"
+ return="android.app.FragmentTransaction"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+</method>
<method name="setCustomAnimations"
return="android.app.FragmentTransaction"
abstract="true"
@@ -142369,6 +142671,21 @@
<parameter name="preferenceScreen" type="android.preference.PreferenceScreen">
</parameter>
</method>
+<method name="showBreadCrumbs"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+<parameter name="shortTitle" type="java.lang.CharSequence">
+</parameter>
+</method>
<method name="startPreferenceFragment"
return="void"
abstract="false"
@@ -142384,6 +142701,21 @@
<parameter name="push" type="boolean">
</parameter>
</method>
+<method name="startPreferenceFragment"
+ 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="ft" type="android.app.FragmentTransaction">
+</parameter>
+</method>
<method name="startWithFragment"
return="void"
abstract="false"
@@ -142427,6 +142759,21 @@
<parameter name="header" type="android.preference.PreferenceActivity.Header">
</parameter>
</method>
+<method name="switchToHeaderInner"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fragmentName" type="java.lang.String">
+</parameter>
+<parameter name="args" type="android.os.Bundle">
+</parameter>
+</method>
<field name="EXTRA_NO_HEADERS"
type="java.lang.String"
transient="false"
@@ -142539,6 +142886,26 @@
visibility="public"
>
</field>
+<field name="breadCrumbShortTitle"
+ type="java.lang.CharSequence"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="breadCrumbTitle"
+ type="java.lang.CharSequence"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="extras"
type="android.os.Bundle"
transient="false"
diff --git a/core/java/android/app/BackStackEntry.java b/core/java/android/app/BackStackRecord.java
index 296b495..e6cc0f9 100644
--- a/core/java/android/app/BackStackEntry.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -18,6 +18,7 @@ package android.app;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
@@ -28,16 +29,20 @@ final class BackStackState implements Parcelable {
final int mTransitionStyle;
final String mName;
final int mIndex;
-
- public BackStackState(FragmentManagerImpl fm, BackStackEntry bse) {
+ final int mBreadCrumbTitleRes;
+ final CharSequence mBreadCrumbTitleText;
+ final int mBreadCrumbShortTitleRes;
+ final CharSequence mBreadCrumbShortTitleText;
+
+ public BackStackState(FragmentManagerImpl fm, BackStackRecord bse) {
int numRemoved = 0;
- BackStackEntry.Op op = bse.mHead;
+ BackStackRecord.Op op = bse.mHead;
while (op != null) {
if (op.removed != null) numRemoved += op.removed.size();
op = op.next;
}
mOps = new int[bse.mNumOp*5 + numRemoved];
-
+
if (!bse.mAddToBackStack) {
throw new IllegalStateException("Not on back stack");
}
@@ -64,21 +69,29 @@ final class BackStackState implements Parcelable {
mTransitionStyle = bse.mTransitionStyle;
mName = bse.mName;
mIndex = bse.mIndex;
+ mBreadCrumbTitleRes = bse.mBreadCrumbTitleRes;
+ mBreadCrumbTitleText = bse.mBreadCrumbTitleText;
+ mBreadCrumbShortTitleRes = bse.mBreadCrumbShortTitleRes;
+ mBreadCrumbShortTitleText = bse.mBreadCrumbShortTitleText;
}
-
+
public BackStackState(Parcel in) {
mOps = in.createIntArray();
mTransition = in.readInt();
mTransitionStyle = in.readInt();
mName = in.readString();
mIndex = in.readInt();
+ mBreadCrumbTitleRes = in.readInt();
+ mBreadCrumbTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ mBreadCrumbShortTitleRes = in.readInt();
+ mBreadCrumbShortTitleText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
}
-
- public BackStackEntry instantiate(FragmentManagerImpl fm) {
- BackStackEntry bse = new BackStackEntry(fm);
+
+ public BackStackRecord instantiate(FragmentManagerImpl fm) {
+ BackStackRecord bse = new BackStackRecord(fm);
int pos = 0;
while (pos < mOps.length) {
- BackStackEntry.Op op = new BackStackEntry.Op();
+ BackStackRecord.Op op = new BackStackRecord.Op();
op.cmd = mOps[pos++];
if (FragmentManagerImpl.DEBUG) Log.v(FragmentManagerImpl.TAG,
"BSE " + bse + " set base fragment #" + mOps[pos]);
@@ -103,10 +116,14 @@ final class BackStackState implements Parcelable {
bse.mName = mName;
bse.mIndex = mIndex;
bse.mAddToBackStack = true;
+ bse.mBreadCrumbTitleRes = mBreadCrumbTitleRes;
+ bse.mBreadCrumbTitleText = mBreadCrumbTitleText;
+ bse.mBreadCrumbShortTitleRes = mBreadCrumbShortTitleRes;
+ bse.mBreadCrumbShortTitleText = mBreadCrumbShortTitleText;
bse.bumpBackStackNesting(1);
return bse;
}
-
+
public int describeContents() {
return 0;
}
@@ -117,14 +134,18 @@ final class BackStackState implements Parcelable {
dest.writeInt(mTransitionStyle);
dest.writeString(mName);
dest.writeInt(mIndex);
+ dest.writeInt(mBreadCrumbTitleRes);
+ TextUtils.writeToParcel(mBreadCrumbTitleText, dest, 0);
+ dest.writeInt(mBreadCrumbShortTitleRes);
+ TextUtils.writeToParcel(mBreadCrumbShortTitleText, dest, 0);
}
-
+
public static final Parcelable.Creator<BackStackState> CREATOR
= new Parcelable.Creator<BackStackState>() {
public BackStackState createFromParcel(Parcel in) {
return new BackStackState(in);
}
-
+
public BackStackState[] newArray(int size) {
return new BackStackState[size];
}
@@ -134,18 +155,19 @@ final class BackStackState implements Parcelable {
/**
* @hide Entry of an operation on the fragment back stack.
*/
-final class BackStackEntry implements FragmentTransaction, Runnable {
+final class BackStackRecord implements FragmentTransaction,
+ FragmentManager.BackStackEntry, Runnable {
static final String TAG = "BackStackEntry";
-
+
final FragmentManagerImpl mManager;
-
+
static final int OP_NULL = 0;
static final int OP_ADD = 1;
static final int OP_REPLACE = 2;
static final int OP_REMOVE = 3;
static final int OP_HIDE = 4;
static final int OP_SHOW = 5;
-
+
static final class Op {
Op next;
Op prev;
@@ -155,7 +177,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
int exitAnim;
ArrayList<Fragment> removed;
}
-
+
Op mHead;
Op mTail;
int mNumOp;
@@ -167,11 +189,34 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
String mName;
boolean mCommitted;
int mIndex;
-
- public BackStackEntry(FragmentManagerImpl manager) {
+
+ int mBreadCrumbTitleRes;
+ CharSequence mBreadCrumbTitleText;
+ int mBreadCrumbShortTitleRes;
+ CharSequence mBreadCrumbShortTitleText;
+
+ public BackStackRecord(FragmentManagerImpl manager) {
mManager = manager;
}
-
+
+ public int getId() {
+ return mIndex;
+ }
+
+ public CharSequence getBreadCrumbTitle() {
+ if (mBreadCrumbTitleRes != 0) {
+ return mManager.mActivity.getText(mBreadCrumbTitleRes);
+ }
+ return mBreadCrumbTitleText;
+ }
+
+ public CharSequence getBreadCrumbShortTitle() {
+ if (mBreadCrumbShortTitleRes != 0) {
+ return mManager.mActivity.getText(mBreadCrumbShortTitleRes);
+ }
+ return mBreadCrumbShortTitleText;
+ }
+
void addOp(Op op) {
if (mHead == null) {
mHead = mTail = op;
@@ -184,7 +229,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
op.exitAnim = mExitAnim;
mNumOp++;
}
-
+
public FragmentTransaction add(Fragment fragment, String tag) {
doAddOp(0, fragment, tag, OP_ADD);
return this;
@@ -206,7 +251,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
}
fragment.mImmediateActivity = mManager.mActivity;
fragment.mFragmentManager = mManager;
-
+
if (tag != null) {
if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
throw new IllegalStateException("Can't change tag of fragment "
@@ -215,7 +260,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
}
fragment.mTag = tag;
}
-
+
if (containerViewId != 0) {
if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
throw new IllegalStateException("Can't change container ID of fragment "
@@ -224,7 +269,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
}
fragment.mContainerId = fragment.mFragmentId = containerViewId;
}
-
+
Op op = new Op();
op.cmd = opcmd;
op.fragment = fragment;
@@ -234,27 +279,27 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
public FragmentTransaction replace(int containerViewId, Fragment fragment) {
return replace(containerViewId, fragment, null);
}
-
+
public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) {
if (containerViewId == 0) {
throw new IllegalArgumentException("Must use non-zero containerViewId");
}
-
+
doAddOp(containerViewId, fragment, tag, OP_REPLACE);
return this;
}
-
+
public FragmentTransaction remove(Fragment fragment) {
if (fragment.mImmediateActivity == null) {
throw new IllegalStateException("Fragment not added: " + fragment);
}
fragment.mImmediateActivity = null;
-
+
Op op = new Op();
op.cmd = OP_REMOVE;
op.fragment = fragment;
addOp(op);
-
+
return this;
}
@@ -262,50 +307,74 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
if (fragment.mImmediateActivity == null) {
throw new IllegalStateException("Fragment not added: " + fragment);
}
-
+
Op op = new Op();
op.cmd = OP_HIDE;
op.fragment = fragment;
addOp(op);
-
+
return this;
}
-
+
public FragmentTransaction show(Fragment fragment) {
if (fragment.mImmediateActivity == null) {
throw new IllegalStateException("Fragment not added: " + fragment);
}
-
+
Op op = new Op();
op.cmd = OP_SHOW;
op.fragment = fragment;
addOp(op);
-
+
return this;
}
-
+
public FragmentTransaction setCustomAnimations(int enter, int exit) {
mEnterAnim = enter;
mExitAnim = exit;
return this;
}
-
+
public FragmentTransaction setTransition(int transition) {
mTransition = transition;
return this;
}
-
+
public FragmentTransaction setTransitionStyle(int styleRes) {
mTransitionStyle = styleRes;
return this;
}
-
+
public FragmentTransaction addToBackStack(String name) {
mAddToBackStack = true;
mName = name;
return this;
}
+ public FragmentTransaction setBreadCrumbTitle(int res) {
+ mBreadCrumbTitleRes = res;
+ mBreadCrumbTitleText = null;
+ return this;
+ }
+
+ public FragmentTransaction setBreadCrumbTitle(CharSequence text) {
+ mBreadCrumbTitleRes = 0;
+ mBreadCrumbTitleText = text;
+ return this;
+ }
+
+ public FragmentTransaction setBreadCrumbShortTitle(int res) {
+ mBreadCrumbShortTitleRes = res;
+ mBreadCrumbShortTitleText = null;
+ return this;
+ }
+
+ public FragmentTransaction setBreadCrumbShortTitle(CharSequence text) {
+ mBreadCrumbShortTitleRes = 0;
+ mBreadCrumbShortTitleText = text;
+ return this;
+ }
+
void bumpBackStackNesting(int amt) {
if (!mAddToBackStack) {
return;
@@ -341,10 +410,10 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
mManager.enqueueAction(this);
return mIndex;
}
-
+
public void run() {
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Run: " + this);
-
+
if (mAddToBackStack) {
if (mIndex < 0) {
throw new IllegalStateException("addToBackStack() called after commit()");
@@ -405,23 +474,23 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
}
}
-
+
op = op.next;
}
-
+
mManager.moveToState(mManager.mCurState, mTransition,
mTransitionStyle, true);
-
+
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
}
-
+
public void popFromBackStack(boolean doStateMove) {
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "popFromBackStack: " + this);
bumpBackStackNesting(-1);
-
+
Op op = mTail;
while (op != null) {
switch (op.cmd) {
@@ -465,10 +534,10 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
}
}
-
+
op = op.prev;
}
-
+
if (doStateMove) {
mManager.moveToState(mManager.mCurState,
FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle, true);
@@ -479,15 +548,15 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
mIndex = -1;
}
}
-
+
public String getName() {
return mName;
}
-
+
public int getTransition() {
return mTransition;
}
-
+
public int getTransitionStyle() {
return mTransitionStyle;
}
diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java
new file mode 100644
index 0000000..0d39d0b
--- /dev/null
+++ b/core/java/android/app/FragmentBreadCrumbs.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Helper class for showing "bread crumbs" representing the fragment
+ * stack in an activity. This is intended to be used with
+ * {@link ActionBar#setCustomNavigationMode(View)
+ * ActionBar.setCustomNavigationMode(View)} to place the bread crumbs in
+ * the navigation area of the action bar.
+ *
+ * <p>The default style for this view is
+ * {@link android.R.style#Widget_FragmentBreadCrumbs}.
+ */
+public class FragmentBreadCrumbs extends ViewGroup
+ implements FragmentManager.OnBackStackChangedListener {
+ Activity mActivity;
+ LayoutInflater mInflater;
+ LinearLayout mContainer;
+
+ // Hahah
+ BackStackRecord mTopEntry;
+
+ public FragmentBreadCrumbs(Context context) {
+ this(context, null);
+ }
+
+ public FragmentBreadCrumbs(Context context, AttributeSet attrs) {
+ this(context, attrs, android.R.style.Widget_FragmentBreadCrumbs);
+ }
+
+ public FragmentBreadCrumbs(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Attach the bread crumbs to their activity. This must be called once
+ * when creating the bread crumbs.
+ */
+ public void setActivity(Activity a) {
+ mActivity = a;
+ mInflater = (LayoutInflater)a.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mContainer = (LinearLayout)mInflater.inflate(
+ com.android.internal.R.layout.fragment_bread_crumbs,
+ this, false);
+ addView(mContainer);
+ a.getFragmentManager().addOnBackStackChangedListener(this);
+ updateCrumbs();
+ }
+
+ /**
+ * Set a custom title for the bread crumbs. This will be the first entry
+ * shown at the left, representing the root of the bread crumbs. If the
+ * title is null, it will not be shown.
+ */
+ public void setTitle(CharSequence title, CharSequence shortTitle) {
+ if (title == null) {
+ mTopEntry = null;
+ } else {
+ mTopEntry = new BackStackRecord((FragmentManagerImpl)
+ mActivity.getFragmentManager());
+ mTopEntry.setBreadCrumbTitle(title);
+ mTopEntry.setBreadCrumbShortTitle(shortTitle);
+ }
+ updateCrumbs();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ // Eventually we should implement our own layout of the views,
+ // rather than relying on a linear layout.
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+
+ int childRight = mPaddingLeft + child.getMeasuredWidth() - mPaddingRight;
+ int childBottom = mPaddingTop + child.getMeasuredHeight() - mPaddingBottom;
+ child.layout(mPaddingLeft, mPaddingTop, childRight, childBottom);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int count = getChildCount();
+
+ int maxHeight = 0;
+ int maxWidth = 0;
+
+ // Find rightmost and bottom-most child
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ measureChild(child, widthMeasureSpec, heightMeasureSpec);
+ maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
+ maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
+ }
+ }
+
+ // Account for padding too
+ maxWidth += mPaddingLeft + mPaddingRight;
+ maxHeight += mPaddingTop + mPaddingBottom;
+
+ // Check against our minimum height and width
+ maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
+ maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
+
+ setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec),
+ resolveSize(maxHeight, heightMeasureSpec));
+ }
+
+ @Override
+ public void onBackStackChanged() {
+ updateCrumbs();
+ }
+
+ void updateCrumbs() {
+ FragmentManager fm = mActivity.getFragmentManager();
+ int numEntries = fm.countBackStackEntries();
+ int numViews = mContainer.getChildCount();
+ for (int i=mTopEntry != null ? -1 : 0; i<numEntries; i++) {
+ FragmentManager.BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i);
+ int viewI = mTopEntry != null ? i+1 : i;
+ if (viewI < numViews) {
+ View v = mContainer.getChildAt(viewI);
+ Object tag = v.getTag();
+ if (tag != bse) {
+ for (int j=viewI; j<numViews; j++) {
+ mContainer.removeViewAt(viewI);
+ }
+ numViews = viewI;
+ }
+ }
+ if (viewI >= numViews) {
+ View item = mInflater.inflate(
+ com.android.internal.R.layout.fragment_bread_crumb_item,
+ this, false);
+ TextView text = (TextView)item.findViewById(com.android.internal.R.id.title);
+ text.setText(bse.getBreadCrumbTitle());
+ item.setTag(bse);
+ if (viewI == 0) {
+ text.setCompoundDrawables(null, null, null, null);
+ }
+ mContainer.addView(item);
+ }
+ }
+ int viewI = mTopEntry != null ? numEntries+1 : numEntries;
+ numViews = mContainer.getChildCount();
+ while (numViews > viewI) {
+ mContainer.removeViewAt(numViews-1);
+ numViews--;
+ }
+ }
+}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index a704ec8..9f95824 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -40,6 +40,48 @@ import java.util.ArrayList;
*/
public interface FragmentManager {
/**
+ * Representation of an entry on the fragment back stack, as created
+ * with {@link FragmentTransaction#addToBackStack(String)
+ * FragmentTransaction.addToBackStack()}. Entries can later be
+ * retrieved with {@link FragmentManager#getBackStackEntry(int)
+ * FragmentManager.getBackStackEntry()}.
+ *
+ * <p>Note that you should never hold on to a BackStackEntry object;
+ * the identifier as returned by {@link #getId} is the only thing that
+ * will be persisted across activity instances.
+ */
+ public interface BackStackEntry {
+ /**
+ * Return the unique identifier for the entry. This is the only
+ * representation of the entry that will persist across activity
+ * instances.
+ */
+ public int getId();
+
+ /**
+ * Return the full bread crumb title for the entry, or null if it
+ * does not have one.
+ */
+ public CharSequence getBreadCrumbTitle();
+
+ /**
+ * Return the short bread crumb title for the entry, or null if it
+ * does not have one.
+ */
+ public CharSequence getBreadCrumbShortTitle();
+ }
+
+ /**
+ * Interface to watch for changes to the back stack.
+ */
+ public interface OnBackStackChangedListener {
+ /**
+ * Called whenever the contents of the back stack change.
+ */
+ public void onBackStackChanged();
+ }
+
+ /**
* Start a series of edit operations on the Fragments associated with
* this FragmentManager.
*/
@@ -105,6 +147,28 @@ public interface FragmentManager {
public boolean popBackStack(int id, int flags);
/**
+ * Return the number of entries currently in the back stack.
+ */
+ public int countBackStackEntries();
+
+ /**
+ * Return the BackStackEntry at index <var>index</var> in the back stack;
+ * entries start index 0 being the bottom of the stack.
+ */
+ public BackStackEntry getBackStackEntry(int index);
+
+ /**
+ * Add a new listener for changes to the fragment back stack.
+ */
+ public void addOnBackStackChangedListener(OnBackStackChangedListener listener);
+
+ /**
+ * Remove a listener that was previously added with
+ * {@link #addOnBackStackChangedListener(OnBackStackChangedListener)}.
+ */
+ public void removeOnBackStackChangedListener(OnBackStackChangedListener listener);
+
+ /**
* Put a reference to a fragment in a Bundle. This Bundle can be
* persisted as saved state, and when later restoring
* {@link #getFragment(Bundle, String)} will return the current
@@ -182,12 +246,14 @@ final class FragmentManagerImpl implements FragmentManager {
ArrayList<Fragment> mActive;
ArrayList<Fragment> mAdded;
ArrayList<Integer> mAvailIndices;
- ArrayList<BackStackEntry> mBackStack;
+ ArrayList<BackStackRecord> mBackStack;
// Must be accessed while locked.
- ArrayList<BackStackEntry> mBackStackIndices;
+ ArrayList<BackStackRecord> mBackStackIndices;
ArrayList<Integer> mAvailBackStackIndices;
+ ArrayList<OnBackStackChangedListener> mBackStackChangeListeners;
+
int mCurState = Fragment.INITIALIZING;
Activity mActivity;
@@ -205,7 +271,7 @@ final class FragmentManagerImpl implements FragmentManager {
}
};
public FragmentTransaction openTransaction() {
- return new BackStackEntry(this);
+ return new BackStackRecord(this);
}
public boolean popBackStack() {
@@ -223,6 +289,27 @@ final class FragmentManagerImpl implements FragmentManager {
return popBackStackState(mActivity.mHandler, null, id, flags);
}
+ public int countBackStackEntries() {
+ return mBackStack != null ? mBackStack.size() : 0;
+ }
+
+ public BackStackEntry getBackStackEntry(int index) {
+ return mBackStack.get(index);
+ }
+
+ public void addOnBackStackChangedListener(OnBackStackChangedListener listener) {
+ if (mBackStackChangeListeners == null) {
+ mBackStackChangeListeners = new ArrayList<OnBackStackChangedListener>();
+ }
+ mBackStackChangeListeners.add(listener);
+ }
+
+ public void removeOnBackStackChangedListener(OnBackStackChangedListener listener) {
+ if (mBackStackChangeListeners != null) {
+ mBackStackChangeListeners.remove(listener);
+ }
+ }
+
public void putFragment(Bundle bundle, String key, Fragment fragment) {
if (fragment.mIndex < 0) {
throw new IllegalStateException("Fragment " + fragment
@@ -696,11 +783,11 @@ final class FragmentManagerImpl implements FragmentManager {
}
}
- public int allocBackStackIndex(BackStackEntry bse) {
+ public int allocBackStackIndex(BackStackRecord bse) {
synchronized (this) {
if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
if (mBackStackIndices == null) {
- mBackStackIndices = new ArrayList<BackStackEntry>();
+ mBackStackIndices = new ArrayList<BackStackRecord>();
}
int index = mBackStackIndices.size();
if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
@@ -716,10 +803,10 @@ final class FragmentManagerImpl implements FragmentManager {
}
}
- public void setBackStackIndex(int index, BackStackEntry bse) {
+ public void setBackStackIndex(int index, BackStackRecord bse) {
synchronized (this) {
if (mBackStackIndices == null) {
- mBackStackIndices = new ArrayList<BackStackEntry>();
+ mBackStackIndices = new ArrayList<BackStackRecord>();
}
int N = mBackStackIndices.size();
if (index < N) {
@@ -785,11 +872,20 @@ final class FragmentManagerImpl implements FragmentManager {
}
}
- public void addBackStackState(BackStackEntry state) {
+ void reportBackStackChanged() {
+ if (mBackStackChangeListeners != null) {
+ for (int i=0; i<mBackStackChangeListeners.size(); i++) {
+ mBackStackChangeListeners.get(i).onBackStackChanged();
+ }
+ }
+ }
+
+ void addBackStackState(BackStackRecord state) {
if (mBackStack == null) {
- mBackStack = new ArrayList<BackStackEntry>();
+ mBackStack = new ArrayList<BackStackRecord>();
}
mBackStack.add(state);
+ reportBackStackChanged();
}
boolean popBackStackState(Handler handler, String name, int id, int flags) {
@@ -801,11 +897,12 @@ final class FragmentManagerImpl implements FragmentManager {
if (last < 0) {
return false;
}
- final BackStackEntry bss = mBackStack.remove(last);
+ final BackStackRecord bss = mBackStack.remove(last);
enqueueAction(new Runnable() {
public void run() {
if (DEBUG) Log.v(TAG, "Popping back stack state: " + bss);
bss.popFromBackStack(true);
+ reportBackStackChanged();
}
});
} else {
@@ -815,7 +912,7 @@ final class FragmentManagerImpl implements FragmentManager {
// the stack.
index = mBackStack.size()-1;
while (index >= 0) {
- BackStackEntry bss = mBackStack.get(index);
+ BackStackRecord bss = mBackStack.get(index);
if (name != null && name.equals(bss.getName())) {
break;
}
@@ -831,7 +928,7 @@ final class FragmentManagerImpl implements FragmentManager {
index--;
// Consume all following entries that match.
while (index >= 0) {
- BackStackEntry bss = mBackStack.get(index);
+ BackStackRecord bss = mBackStack.get(index);
if ((name != null && name.equals(bss.getName()))
|| (id >= 0 && id == bss.mIndex)) {
index--;
@@ -844,8 +941,8 @@ final class FragmentManagerImpl implements FragmentManager {
if (index == mBackStack.size()-1) {
return false;
}
- final ArrayList<BackStackEntry> states
- = new ArrayList<BackStackEntry>();
+ final ArrayList<BackStackRecord> states
+ = new ArrayList<BackStackRecord>();
for (int i=mBackStack.size()-1; i>index; i--) {
states.add(mBackStack.remove(i));
}
@@ -856,6 +953,7 @@ final class FragmentManagerImpl implements FragmentManager {
if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i));
states.get(i).popFromBackStack(i == LAST);
}
+ reportBackStackChanged();
}
});
}
@@ -1073,9 +1171,9 @@ final class FragmentManagerImpl implements FragmentManager {
// Build the back stack.
if (fms.mBackStack != null) {
- mBackStack = new ArrayList<BackStackEntry>(fms.mBackStack.length);
+ mBackStack = new ArrayList<BackStackRecord>(fms.mBackStack.length);
for (int i=0; i<fms.mBackStack.length; i++) {
- BackStackEntry bse = fms.mBackStack[i].instantiate(this);
+ BackStackRecord bse = fms.mBackStack[i].instantiate(this);
if (DEBUG) Log.v(TAG, "restoreAllState: adding bse #" + i
+ " (index " + bse.mIndex + "): " + bse);
mBackStack.add(bse);
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 9d44106..09d8d26 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -88,7 +88,7 @@ public interface FragmentTransaction {
/**
* @return <code>true</code> if this transaction contains no operations,
- * <code>false</code> otherwise.
+ * <code>false</code> otherwise.
*/
public boolean isEmpty();
@@ -111,14 +111,65 @@ public interface FragmentTransaction {
/** Fragment is being removed */
public final int TRANSIT_FRAGMENT_CLOSE = 2 | TRANSIT_EXIT_MASK;
+ /**
+ * Set specific animation resources to run for the fragments that are
+ * entering and exiting in this transaction.
+ */
public FragmentTransaction setCustomAnimations(int enter, int exit);
+ /**
+ * Select a standard transition animation for this transaction. May be
+ * one of {@link #TRANSIT_NONE}, {@link #TRANSIT_FRAGMENT_OPEN},
+ * or {@link #TRANSIT_FRAGMENT_CLOSE}
+ */
public FragmentTransaction setTransition(int transit);
+
+ /**
+ * Set a custom style resource that will be used for resolving transit
+ * animations.
+ */
public FragmentTransaction setTransitionStyle(int styleRes);
+ /**
+ * Add this transaction to the back stack. This means that the transaction
+ * will be remembered after it is committed, and will reverse its operation
+ * when later popped off the stack.
+ *
+ * @param name An optional name for this back stack state, or null.
+ */
public FragmentTransaction addToBackStack(String name);
/**
+ * Set the full title to show as a bread crumb when this transaction
+ * is on the back stack, as used by {@link FragmentBreadCrumbs}.
+ *
+ * @param res A string resource containing the title.
+ */
+ public FragmentTransaction setBreadCrumbTitle(int res);
+
+ /**
+ * Like {@link #setBreadCrumbTitle(int)} but taking a raw string; this
+ * method is <em>not</em> recommended, as the string can not be changed
+ * later if the locale changes.
+ */
+ public FragmentTransaction setBreadCrumbTitle(CharSequence text);
+
+ /**
+ * Set the short title to show as a bread crumb when this transaction
+ * is on the back stack, as used by {@link FragmentBreadCrumbs}.
+ *
+ * @param res A string resource containing the title.
+ */
+ public FragmentTransaction setBreadCrumbShortTitle(int res);
+
+ /**
+ * Like {@link #setBreadCrumbShortTitle(int)} but taking a raw string; this
+ * method is <em>not</em> recommended, as the string can not be changed
+ * later if the locale changes.
+ */
+ public FragmentTransaction setBreadCrumbShortTitle(CharSequence text);
+
+ /**
* Schedules a commit of this transaction. Note that the commit does
* not happen immediately; it will be scheduled as work on the main thread
* to be done the next time that thread is ready.
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 4247ae5..e78d2af 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -22,6 +22,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Fragment;
+import android.app.FragmentBreadCrumbs;
import android.app.FragmentTransaction;
import android.app.ListActivity;
import android.content.Context;
@@ -117,7 +118,6 @@ public abstract class PreferenceActivity extends ListActivity implements
// Constants for state save/restore
private static final String HEADERS_TAG = ":android:headers";
private static final String CUR_HEADER_TAG = ":android:cur_header";
- private static final String SINGLE_PANE_TAG = ":android:single_pane";
private static final String PREFERENCES_TAG = ":android:preferences";
/**
@@ -169,6 +169,8 @@ public abstract class PreferenceActivity extends ListActivity implements
private View mPrefsContainer;
+ private FragmentBreadCrumbs mFragmentBreadCrumbs;
+
private boolean mSinglePane;
private Header mCurHeader;
@@ -300,6 +302,18 @@ public abstract class PreferenceActivity extends ListActivity implements
public CharSequence summary;
/**
+ * Optional text to show as the title in the bread crumb.
+ * @attr ref android.R.styleable#PreferenceHeader_breadCrumbTitle
+ */
+ public CharSequence breadCrumbTitle;
+
+ /**
+ * Optional text to show as the short title in the bread crumb.
+ * @attr ref android.R.styleable#PreferenceHeader_breadCrumbShortTitle
+ */
+ public CharSequence breadCrumbShortTitle;
+
+ /**
* Optional icon resource to show for this header.
* @attr ref android.R.styleable#PreferenceHeader_icon
*/
@@ -341,6 +355,8 @@ public abstract class PreferenceActivity extends ListActivity implements
dest.writeLong(id);
TextUtils.writeToParcel(title, dest, flags);
TextUtils.writeToParcel(summary, dest, flags);
+ TextUtils.writeToParcel(breadCrumbTitle, dest, flags);
+ TextUtils.writeToParcel(breadCrumbShortTitle, dest, flags);
dest.writeInt(iconRes);
dest.writeString(fragment);
dest.writeBundle(fragmentArguments);
@@ -357,6 +373,8 @@ public abstract class PreferenceActivity extends ListActivity implements
id = in.readLong();
title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ breadCrumbTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ breadCrumbShortTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
iconRes = in.readInt();
fragment = in.readString();
fragmentArguments = in.readBundle();
@@ -405,7 +423,6 @@ public abstract class PreferenceActivity extends ListActivity implements
setSelectedHeader(mHeaders.get(curHeader));
}
}
- mSinglePane = savedInstanceState.getBoolean(SINGLE_PANE_TAG);
} else {
if (initialFragment != null && mSinglePane) {
@@ -537,7 +554,11 @@ public abstract class PreferenceActivity extends ListActivity implements
public boolean onIsMultiPane() {
Configuration config = getResources().getConfiguration();
if ((config.screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK)
- == Configuration.SCREENLAYOUT_SIZE_XLARGE
+ == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
+ return true;
+ }
+ if ((config.screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK)
+ == Configuration.SCREENLAYOUT_SIZE_LARGE
&& config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
return true;
}
@@ -649,6 +670,10 @@ public abstract class PreferenceActivity extends ListActivity implements
com.android.internal.R.styleable.PreferenceHeader_title);
header.summary = sa.getText(
com.android.internal.R.styleable.PreferenceHeader_summary);
+ header.breadCrumbTitle = sa.getText(
+ com.android.internal.R.styleable.PreferenceHeader_breadCrumbTitle);
+ header.breadCrumbShortTitle = sa.getText(
+ com.android.internal.R.styleable.PreferenceHeader_breadCrumbShortTitle);
header.iconRes = sa.getResourceId(
com.android.internal.R.styleable.PreferenceHeader_icon, 0);
header.fragment = sa.getString(
@@ -741,7 +766,6 @@ public abstract class PreferenceActivity extends ListActivity implements
}
}
}
- outState.putBoolean(SINGLE_PANE_TAG, mSinglePane);
if (mPreferenceManager != null) {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
@@ -837,6 +861,20 @@ public abstract class PreferenceActivity extends ListActivity implements
startActivity(intent);
}
+ /**
+ * Change the base title of the bread crumbs for the current preferences.
+ * This will normally be called for you. See
+ * {@link android.app.FragmentBreadCrumbs} for more information.
+ */
+ public void showBreadCrumbs(CharSequence title, CharSequence shortTitle) {
+ if (mFragmentBreadCrumbs == null) {
+ mFragmentBreadCrumbs = new FragmentBreadCrumbs(this);
+ mFragmentBreadCrumbs.setActivity(this);
+ getActionBar().setCustomNavigationMode(mFragmentBreadCrumbs);
+ }
+ mFragmentBreadCrumbs.setTitle(title, shortTitle);
+ }
+
void setSelectedHeader(Header header) {
mCurHeader = header;
int index = mHeaders.indexOf(header);
@@ -845,6 +883,21 @@ public abstract class PreferenceActivity extends ListActivity implements
} else {
getListView().clearChoices();
}
+ if (header != null) {
+ CharSequence title = header.breadCrumbTitle;
+ if (title == null) title = header.title;
+ if (title == null) title = getTitle();
+ showBreadCrumbs(title, header.breadCrumbShortTitle);
+ } else {
+ showBreadCrumbs(getTitle(), null);
+ }
+ }
+
+ public void switchToHeaderInner(String fragmentName, Bundle args) {
+ getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
+ Fragment f = Fragment.instantiate(this, fragmentName, args);
+ getFragmentManager().openTransaction().replace(
+ com.android.internal.R.id.prefs, f).commit();
}
/**
@@ -856,12 +909,7 @@ public abstract class PreferenceActivity extends ListActivity implements
*/
public void switchToHeader(String fragmentName, Bundle args) {
setSelectedHeader(null);
-
- getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
-
- Fragment f = Fragment.instantiate(this, fragmentName, args);
- getFragmentManager().openTransaction().replace(
- com.android.internal.R.id.prefs, f).commit();
+ switchToHeaderInner(fragmentName, args);
}
/**
@@ -871,8 +919,7 @@ public abstract class PreferenceActivity extends ListActivity implements
* @param header The new header to display.
*/
public void switchToHeader(Header header) {
- switchToHeader(header.fragment, header.fragmentArguments);
- mCurHeader = header;
+ switchToHeaderInner(header.fragment, header.fragmentArguments);
setSelectedHeader(header);
}
@@ -930,17 +977,32 @@ public abstract class PreferenceActivity extends ListActivity implements
*/
public void startPreferenceFragment(Fragment fragment, boolean push) {
FragmentTransaction transaction = getFragmentManager().openTransaction();
- transaction.replace(com.android.internal.R.id.prefs, fragment);
+ startPreferenceFragment(fragment, transaction);
if (push) {
transaction.addToBackStack(BACK_STACK_PREFS);
}
transaction.commit();
}
+ /**
+ * Start a new fragment.
+ *
+ * @param fragment The fragment to start
+ * @param ft The FragmentTransaction in which to perform this operation.
+ * Will not be added to the back stack or committed for you; you use do that.
+ */
+ public void startPreferenceFragment(Fragment fragment, FragmentTransaction ft) {
+ ft.replace(com.android.internal.R.id.prefs, fragment);
+ }
+
@Override
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras());
- startPreferenceFragment(f, true);
+ FragmentTransaction transaction = getFragmentManager().openTransaction();
+ startPreferenceFragment(f, transaction);
+ transaction.setBreadCrumbTitle(pref.getTitle());
+ transaction.addToBackStack(BACK_STACK_PREFS);
+ transaction.commit();
return true;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 00efa90..ac65e09 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8745,7 +8745,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
invalidate();
refreshDrawableState();
- dispatchSetSelected(activated);
+ dispatchSetActivated(activated);
}
}
diff --git a/core/res/res/color/primary_text_dark.xml b/core/res/res/color/primary_text_dark.xml
index 39c9e22..3dd73e7 100644
--- a/core/res/res/color/primary_text_dark.xml
+++ b/core/res/res/color/primary_text_dark.xml
@@ -19,7 +19,6 @@
<item android:state_window_focused="false" android:color="@android:color/bright_foreground_dark"/>
<item android:state_pressed="true" android:color="@android:color/bright_foreground_dark_inverse"/>
<item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
<item android:color="@android:color/bright_foreground_dark"/> <!-- not selected -->
-
</selector>
-
diff --git a/core/res/res/color/primary_text_dark_focused.xml b/core/res/res/color/primary_text_dark_focused.xml
index 7f3906a..c97c0bd 100644
--- a/core/res/res/color/primary_text_dark_focused.xml
+++ b/core/res/res/color/primary_text_dark_focused.xml
@@ -16,6 +16,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse" />
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse" />
<item android:state_focused="true" android:color="@android:color/bright_foreground_dark_inverse" />
<item android:state_pressed="true" android:color="@android:color/bright_foreground_dark_inverse" />
<item android:color="@android:color/bright_foreground_dark" />
diff --git a/core/res/res/color/primary_text_dark_nodisable.xml b/core/res/res/color/primary_text_dark_nodisable.xml
index be1b9f9..443f7f4 100644
--- a/core/res/res/color/primary_text_dark_nodisable.xml
+++ b/core/res/res/color/primary_text_dark_nodisable.xml
@@ -16,6 +16,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
<item android:color="@android:color/bright_foreground_dark"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/primary_text_light.xml b/core/res/res/color/primary_text_light.xml
index e112034..a12c6b4 100644
--- a/core/res/res/color/primary_text_light.xml
+++ b/core/res/res/color/primary_text_light.xml
@@ -19,6 +19,7 @@
<item android:state_window_focused="false" android:color="@android:color/bright_foreground_light"/>
<item android:state_pressed="true" android:color="@android:color/bright_foreground_light"/>
<item android:state_selected="true" android:color="@android:color/bright_foreground_light"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
<item android:color="@android:color/bright_foreground_light"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/primary_text_light_nodisable.xml b/core/res/res/color/primary_text_light_nodisable.xml
index 2d35470..051cccf 100644
--- a/core/res/res/color/primary_text_light_nodisable.xml
+++ b/core/res/res/color/primary_text_light_nodisable.xml
@@ -16,6 +16,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/bright_foreground_light"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
<item android:color="@android:color/bright_foreground_light"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/secondary_text_dark.xml b/core/res/res/color/secondary_text_dark.xml
index c195ef0..1a38fa9 100644
--- a/core/res/res/color/secondary_text_dark.xml
+++ b/core/res/res/color/secondary_text_dark.xml
@@ -20,6 +20,7 @@
<item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_inverse_disabled"/>
<item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_inverse_disabled"/>
<item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
<item android:state_pressed="true" android:color="@android:color/dim_foreground_dark_inverse"/>
<item android:state_enabled="false" android:color="@android:color/dim_foreground_dark_disabled"/>
<item android:color="@android:color/dim_foreground_dark"/> <!-- not selected -->
diff --git a/core/res/res/color/secondary_text_dark_nodisable.xml b/core/res/res/color/secondary_text_dark_nodisable.xml
index 2c87a25..cbc7b02 100644
--- a/core/res/res/color/secondary_text_dark_nodisable.xml
+++ b/core/res/res/color/secondary_text_dark_nodisable.xml
@@ -16,5 +16,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
<item android:color="@android:color/dim_foreground_dark"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/secondary_text_light.xml b/core/res/res/color/secondary_text_light.xml
index 99249a5..293f4aa 100644
--- a/core/res/res/color/secondary_text_light.xml
+++ b/core/res/res/color/secondary_text_light.xml
@@ -22,6 +22,7 @@
<item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
<item android:state_pressed="true" android:color="@android:color/dim_foreground_light"/>
<item android:state_selected="true" android:color="@android:color/dim_foreground_light"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
<item android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
<item android:color="@android:color/dim_foreground_light"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/secondary_text_light_nodisable.xml b/core/res/res/color/secondary_text_light_nodisable.xml
index 2c87a25..cbc7b02 100644
--- a/core/res/res/color/secondary_text_light_nodisable.xml
+++ b/core/res/res/color/secondary_text_light_nodisable.xml
@@ -16,5 +16,6 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
<item android:color="@android:color/dim_foreground_dark"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/drawable-hdpi/nav_divider.png b/core/res/res/drawable-hdpi/nav_divider.png
new file mode 100644
index 0000000..7ca3e61
--- /dev/null
+++ b/core/res/res/drawable-hdpi/nav_divider.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/nav_divider.png b/core/res/res/drawable-mdpi/nav_divider.png
new file mode 100644
index 0000000..c9413d7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/nav_divider.png
Binary files differ
diff --git a/core/res/res/layout-port/preference_header_item.xml b/core/res/res/layout-port/preference_header_item.xml
new file mode 100644
index 0000000..cc76c8e
--- /dev/null
+++ b/core/res/res/layout-port/preference_header_item.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Layout of a header item in PreferenceActivity. -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="96dp"
+ android:background="?android:attr/activatedBackgroundIndicator"
+ android:paddingRight="?android:attr/scrollbarSize">
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center"
+ android:paddingLeft="4dip"
+ android:paddingRight="4dip"
+ android:paddingTop="4dip"
+ android:paddingBottom="4dip">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginBottom="2dip" />
+
+ <TextView android:id="@+android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginBottom="2dip"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+
+ <TextView android:id="@+android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:ellipsize="end"
+ android:maxLines="2" />
+
+ </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/fragment_bread_crumb_item.xml b/core/res/res/layout/fragment_bread_crumb_item.xml
new file mode 100644
index 0000000..408f6e8
--- /dev/null
+++ b/core/res/res/layout/fragment_bread_crumb_item.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:textAppearance="?android:attr/textAppearanceMediumInverse"
+ android:drawableLeft="@drawable/nav_divider"
+ android:paddingLeft="12dp"
+ android:drawablePadding="12dp"
+ />
diff --git a/core/res/res/layout/fragment_bread_crumbs.xml b/core/res/res/layout/fragment_bread_crumbs.xml
new file mode 100644
index 0000000..f289e14
--- /dev/null
+++ b/core/res/res/layout/fragment_bread_crumbs.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+</LinearLayout>
diff --git a/core/res/res/layout/preference_header_item.xml b/core/res/res/layout/preference_header_item.xml
index 80a3ac2..aba7b2a 100644
--- a/core/res/res/layout/preference_header_item.xml
+++ b/core/res/res/layout/preference_header_item.xml
@@ -54,6 +54,7 @@
android:layout_below="@android:id/title"
android:layout_alignLeft="@android:id/title"
android:textAppearance="?android:attr/textAppearanceSmall"
+ android:ellipsize="end"
android:maxLines="2" />
</RelativeLayout>
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index fe950b2..9661c64 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -33,7 +33,7 @@
android:orientation="vertical"
android:layout_width="0px"
android:layout_height="match_parent"
- android:layout_weight="1">
+ android:layout_weight="10">
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
@@ -52,7 +52,7 @@
<FrameLayout android:id="@+id/prefs"
android:layout_width="0px"
android:layout_height="match_parent"
- android:layout_weight="3"
+ android:layout_weight="33"
android:visibility="gone" />
</LinearLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index b3d39f3..2dec5c5 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3561,6 +3561,10 @@
<attr name="title" />
<!-- The summary for the item. -->
<attr name="summary" format="string" />
+ <!-- The title for the bread crumb of this item. -->
+ <attr name="breadCrumbTitle" format="string" />
+ <!-- The short title for the bread crumb of this item. -->
+ <attr name="breadCrumbShortTitle" format="string" />
<!-- An icon for the item. -->
<attr name="icon" />
<!-- The fragment that is displayed when the user selects this item. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 3b69acb..fbee438 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1352,6 +1352,8 @@
<public type="attr" name="popupMenuStyle" />
<public type="attr" name="textAppearanceLargePopupMenu" />
<public type="attr" name="textAppearanceSmallPopupMenu" />
+ <public type="attr" name="breadCrumbTitle" />
+ <public type="attr" name="breadCrumbShortTitle" />
<public type="anim" name="animator_fade_in" />
<public type="anim" name="animator_fade_out" />
@@ -1390,6 +1392,7 @@
<public type="style" name="Widget.ActionButton.CloseMode" />
<public type="style" name="TextAppearance.Widget.PopupMenu.Large" />
<public type="style" name="TextAppearance.Widget.PopupMenu.Small" />
+ <public type="style" name="Widget.FragmentBreadCrumbs" />
<public type="string" name="selectTextMode" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 9ba0131..1db6f87 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -563,6 +563,11 @@
<item name="android:popupBackground">@android:drawable/editbox_dropdown_background_dark</item>
</style>
+ <!-- Default style for {@link android.app.FragmentBreadCrumbs} view. -->
+ <style name="Widget.FragmentBreadCrumbs">
+ <item name="android:padding">4dp</item>
+ </style>
+
<style name="Widget.KeyboardView" parent="android:Widget">
<item name="android:background">@android:drawable/keyboard_background</item>
<item name="android:keyBackground">@android:drawable/btn_keyboard_key</item>