Merge "Add a way to insert a parent bread crumb so that deep linked settings can navigate up."
diff --git a/api/current.xml b/api/current.xml
index e2ceb3f..008de2b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -29871,6 +29871,36 @@
<parameter name="a" type="android.app.Activity">
</parameter>
</method>
+<method name="setMaxVisible"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="visibleCrumbs" type="int">
+</parameter>
+</method>
+<method name="setParentTitle"
+ 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>
+<parameter name="listener" type="android.view.View.OnClickListener">
+</parameter>
+</method>
<method name="setTitle"
return="void"
abstract="false"
@@ -148256,6 +148286,23 @@
<parameter name="view" type="android.view.View">
</parameter>
</method>
+<method name="setParentTitle"
+ 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>
+<parameter name="listener" type="android.view.View.OnClickListener">
+</parameter>
+</method>
<method name="setPreferenceScreen"
return="void"
abstract="false"
@@ -251222,7 +251269,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
</parameter>
</method>
</interface>
diff --git a/core/java/android/app/FragmentBreadCrumbs.java b/core/java/android/app/FragmentBreadCrumbs.java
index 8d76ffe..fb89099 100644
--- a/core/java/android/app/FragmentBreadCrumbs.java
+++ b/core/java/android/app/FragmentBreadCrumbs.java
@@ -45,6 +45,10 @@
// Hahah
BackStackRecord mTopEntry;
+ BackStackRecord mParentEntry;
+
+ /** Listener to inform when a parent entry is clicked */
+ private OnClickListener mParentClickListener;
public FragmentBreadCrumbs(Context context) {
this(context, null);
@@ -75,27 +79,51 @@
}
/**
- * The maximum number of crumbs to show.
- * @hide
+ * The maximum number of breadcrumbs to show. Older fragment headers will be hidden from view.
+ * @param visibleCrumbs the number of visible breadcrumbs. This should be greater than zero.
*/
public void setMaxVisible(int visibleCrumbs) {
+ if (visibleCrumbs < 1) {
+ throw new IllegalArgumentException("visibleCrumbs must be greater than zero");
+ }
mMaxVisible = visibleCrumbs;
}
/**
+ * Inserts an optional parent entry at the first position in the breadcrumbs. Selecting this
+ * entry will result in a call to the specified listener's
+ * {@link android.view.View.OnClickListener#onClick(View)}
+ * method.
+ *
+ * @param title the title for the parent entry
+ * @param shortTitle the short title for the parent entry
+ * @param listener the {@link android.view.View.OnClickListener} to be called when clicked.
+ * A null will result in no action being taken when the parent entry is clicked.
+ */
+ public void setParentTitle(CharSequence title, CharSequence shortTitle,
+ OnClickListener listener) {
+ mParentEntry = createBackStackEntry(title, shortTitle);
+ mParentClickListener = listener;
+ updateCrumbs();
+ }
+
+ private BackStackRecord createBackStackEntry(CharSequence title, CharSequence shortTitle) {
+ if (title == null) return null;
+
+ final BackStackRecord entry = new BackStackRecord(
+ (FragmentManagerImpl) mActivity.getFragmentManager());
+ entry.setBreadCrumbTitle(title);
+ entry.setBreadCrumbShortTitle(shortTitle);
+ return entry;
+ }
+
+ /**
* 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);
- }
+ mTopEntry = createBackStackEntry(title, shortTitle);
updateCrumbs();
}
@@ -151,41 +179,66 @@
updateCrumbs();
}
+ /**
+ * Returns the number of entries before the backstack, including the title of the current
+ * fragment and any custom parent title that was set.
+ */
+ private int getPreEntryCount() {
+ return (mTopEntry != null ? 1 : 0) + (mParentEntry != null ? 1 : 0);
+ }
+
+ /**
+ * Returns the pre-entry corresponding to the index. If there is a parent and a top entry
+ * set, parent has an index of zero and top entry has an index of 1. Returns null if the
+ * specified index doesn't exist or is null.
+ * @param index should not be more than {@link #getPreEntryCount()} - 1
+ */
+ private BackStackEntry getPreEntry(int index) {
+ // If there's a parent entry, then return that for zero'th item, else top entry.
+ if (mParentEntry != null) {
+ return index == 0 ? mParentEntry : mTopEntry;
+ } else {
+ return mTopEntry;
+ }
+ }
+
void updateCrumbs() {
FragmentManager fm = mActivity.getFragmentManager();
int numEntries = fm.countBackStackEntries();
+ int numPreEntries = getPreEntryCount();
int numViews = mContainer.getChildCount();
- for (int i = mTopEntry != null ? -1 : 0; i < numEntries; i++) {
- BackStackEntry bse = i == -1 ? mTopEntry : fm.getBackStackEntry(i);
- int viewI = mTopEntry != null ? i + 1 : i;
- if (viewI < numViews) {
- View v = mContainer.getChildAt(viewI);
+ for (int i = 0; i < numEntries + numPreEntries; i++) {
+ BackStackEntry bse = i < numPreEntries
+ ? getPreEntry(i)
+ : fm.getBackStackEntry(i - numPreEntries);
+ if (i < numViews) {
+ View v = mContainer.getChildAt(i);
Object tag = v.getTag();
if (tag != bse) {
- for (int j = viewI; j < numViews; j++) {
- mContainer.removeViewAt(viewI);
+ for (int j = i; j < numViews; j++) {
+ mContainer.removeViewAt(i);
}
- numViews = viewI;
+ numViews = i;
}
}
- if (viewI >= numViews) {
+ if (i >= numViews) {
final View item = mInflater.inflate(
com.android.internal.R.layout.fragment_bread_crumb_item,
this, false);
final TextView text = (TextView) item.findViewById(com.android.internal.R.id.title);
text.setText(bse.getBreadCrumbTitle());
text.setTag(bse);
- if (viewI == 0) {
+ if (i == 0) {
item.findViewById(com.android.internal.R.id.left_icon).setVisibility(View.GONE);
}
mContainer.addView(item);
text.setOnClickListener(mOnClickListener);
}
}
- int viewI = mTopEntry != null ? numEntries + 1 : numEntries;
+ int viewI = numEntries + numPreEntries;
numViews = mContainer.getChildCount();
while (numViews > viewI) {
- mContainer.removeViewAt(numViews-1);
+ mContainer.removeViewAt(numViews - 1);
numViews--;
}
// Adjust the visibility and availability of the bread crumbs and divider
@@ -208,8 +261,14 @@
public void onClick(View v) {
if (v.getTag() instanceof BackStackEntry) {
BackStackEntry bse = (BackStackEntry) v.getTag();
- mActivity.getFragmentManager().popBackStack(bse.getId(),
- bse == mTopEntry? FragmentManager.POP_BACK_STACK_INCLUSIVE : 0);
+ if (bse == mParentEntry) {
+ if (mParentClickListener != null) {
+ mParentClickListener.onClick(v);
+ }
+ } else {
+ mActivity.getFragmentManager().popBackStack(bse.getId(),
+ bse == mTopEntry? FragmentManager.POP_BACK_STACK_INCLUSIVE : 0);
+ }
}
}
};
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index d9039ab..7a186f3 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -1005,6 +1005,21 @@
mFragmentBreadCrumbs.setActivity(this);
}
mFragmentBreadCrumbs.setTitle(title, shortTitle);
+ mFragmentBreadCrumbs.setParentTitle(null, null, null);
+ }
+
+ /**
+ * Should be called after onCreate to ensure that the breadcrumbs, if any, were created.
+ * This prepends a title to the fragment breadcrumbs and attaches a listener to any clicks
+ * on the parent entry.
+ * @param title the title for the breadcrumb
+ * @param shortTitle the short title for the breadcrumb
+ */
+ public void setParentTitle(CharSequence title, CharSequence shortTitle,
+ OnClickListener listener) {
+ if (mFragmentBreadCrumbs != null) {
+ mFragmentBreadCrumbs.setParentTitle(title, shortTitle, listener);
+ }
}
void setSelectedHeader(Header header) {