From b61cf51d850d37a4d82b93b8ee0d190930421a46 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Sun, 12 Sep 2010 08:17:50 -0700 Subject: [PATCH] Breadcrumbs in the action bar for navigating up one level and showing current title. Change-Id: I595e06549b888bd67c6dddd599a4cc77416c3a41 --- AndroidManifest.xml | 2 +- res/drawable-hdpi/nav_divider.png | Bin 0 -> 1012 bytes res/drawable-mdpi/nav_divider.png | Bin 0 -> 2846 bytes res/layout/settings_actionbar.xml | 64 +++++++ src/com/android/settings/Settings.java | 172 ++++++++++++++---- .../settings/SettingsPreferenceFragment.java | 6 +- 6 files changed, 211 insertions(+), 33 deletions(-) create mode 100644 res/drawable-hdpi/nav_divider.png create mode 100644 res/drawable-mdpi/nav_divider.png create mode 100644 res/layout/settings_actionbar.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index e93cb2e3577..b6a422e2259 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -49,7 +49,7 @@ + android:theme="@android:style/Theme.Holo"> diff --git a/res/drawable-hdpi/nav_divider.png b/res/drawable-hdpi/nav_divider.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca3e6131b03adfd1b2d2fa7a29ce314d086a981 GIT binary patch literal 1012 zcmbVL%Wl&^6m^MIRW0qltVV9d0ueu(_@SD}Pa1?vl|~{f#KfL7R%?$LPl?+Vf(=za z0R(@*2f%_gUx36#_X?`?RG+ z_P@RG#$?+%^#^nxkLUyv#Mv<(BG66Y0qP+bpFI15wmGgbO8Nsj2p^geP6b%$2xXcx zG{IhlGx%Ow?Zk*T{KR1P6^sS-R(!GhmjHUoqJ%rG#NpP zCd+FhVXvLs51 zC@W1_GgZZuBrsn*vqs{P+4F+AEhbs~n9|%7#mQtMOjH4r15q{%qvBAMCevsZCmDrh zGb=V~1`ibxNphOt3{;G8h>xkoGf!tBqr zYbICOZ@XKz=O}^tuefK}_8{%m16SnuC_@`7t{ciuku>ey*D#$4Cm^*%UH GU;YMn*)?AP literal 0 HcmV?d00001 diff --git a/res/drawable-mdpi/nav_divider.png b/res/drawable-mdpi/nav_divider.png new file mode 100644 index 0000000000000000000000000000000000000000..c9413d7c147a56adb8ddc31ad5bee47d764f6f7e GIT binary patch literal 2846 zcmV+(3*q#MP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0000h2m*os|IXidkiEER8B8007{{(t3GL w+sT( + + + + + + + + + + + + + + + diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 2ce0bccdd4e..50aa1df12b2 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -18,6 +18,7 @@ package com.android.settings; import android.app.Activity; import android.app.Fragment; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.preference.Preference; @@ -25,8 +26,13 @@ import android.preference.PreferenceFragment; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; import android.text.TextUtils; +import android.util.AttributeSet; import android.util.Log; +import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; +import android.widget.LinearLayout; +import android.widget.TextView; import java.util.ArrayList; @@ -37,6 +43,8 @@ public class Settings extends Activity implements PreferenceFragment.OnPreferenceStartFragmentCallback, SettingsPreferenceFragment.OnStateListener { + private static final boolean DBG = false; + private static final String TAG = "Settings"; private static final String KEY_PARENT = "parent"; @@ -52,22 +60,13 @@ public class Settings extends Activity public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args"; - // Temporary, until all top-level settings are converted to fragments private static final String BACK_STACK_PREFS = ":settings:prefs"; private View mPrefsPane; private View mMainPane; private boolean mSinglePane; - private ArrayList mTrail = new ArrayList(); - - /* - @Override - protected void onResume() { - super.onResume(); - findPreference(KEY_CALL_SETTINGS).setEnabled(!AirplaneModeEnabler.isAirplaneModeOn(this)); - } - */ + private BreadCrumbs mBreadCrumbs; @Override protected void onCreate(Bundle savedInstanceState) { @@ -82,6 +81,8 @@ public class Settings extends Activity String initialFragment = intent.getStringExtra(EXTRA_SHOW_FRAGMENT); Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS); + createActionBar(); + if (mSinglePane) { if (initialFragment != null) { showFragment(initialFragment, initialArguments); @@ -111,11 +112,21 @@ public class Settings extends Activity } } + private void createActionBar() { + LayoutInflater inflater = (LayoutInflater) + getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View customNavBar = inflater.inflate(R.layout.settings_actionbar, null, false); + getActionBar().setCustomNavigationMode(customNavBar); + mBreadCrumbs = (BreadCrumbs) customNavBar.findViewById(R.id.bread_crumbs); + mBreadCrumbs.setActivity(this); + } + boolean showFragment(Preference preference) { if (mSinglePane) { startWithFragment(preference.getFragment(), preference.getExtras()); return false; } else { + mBreadCrumbs.clear(); return showFragment(preference.getFragment(), preference.getExtras()); } } @@ -129,10 +140,13 @@ public class Settings extends Activity } private boolean showFragment(String fragmentClass, Bundle extras) { - Fragment f = Fragment.instantiate(this, fragmentClass, extras); + if (DBG) Log.d(TAG, "showFragment"); + Fragment f = Fragment.instantiate(this, fragmentClass, extras); if (f instanceof SettingsPreferenceFragment) { ((SettingsPreferenceFragment) f).setOnStateListener(this); } + mBreadCrumbs.clear(); + getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE); getFragmentManager().openTransaction().replace(R.id.prefs, f).commit(); return true; } @@ -140,41 +154,28 @@ public class Settings extends Activity private void addToBreadCrumbs(Fragment fragment) { final CharSequence title = ((PreferenceFragment) fragment) .getPreferenceScreen().getTitle(); - if (mSinglePane) mTrail.clear(); - if (mTrail.size() == 0 || !TextUtils.equals(title, mTrail.get(mTrail.size() - 1))) { - mTrail.add(title); - updateTitle(); + if (mSinglePane) { + mBreadCrumbs.clear(); } + mBreadCrumbs.push(title); } private void removeFromBreadCrumbs(Fragment fragment) { - if (mTrail.size() > 0) { - mTrail.remove(mTrail.size() - 1); - } - updateTitle(); - } - - private void updateTitle() { - String trail = ""; - for (CharSequence trailPart : mTrail) { - if (trail.length() != 0) - trail += " | "; - trail = trail + trailPart; - } - setTitle(trail); + mBreadCrumbs.pop(((PreferenceFragment) fragment).getPreferenceScreen().getTitle()); + mBreadCrumbs.update(); } public void onCreated(SettingsPreferenceFragment fragment) { - Log.d(TAG, "Fragment created " + fragment + " (name: " + fragment.getClass() + ")"); + if (DBG) Log.d(TAG, "Fragment created " + fragment); addToBreadCrumbs(fragment); } public void onDestroyed(SettingsPreferenceFragment fragment) { - removeFromBreadCrumbs(fragment); Log.d(TAG, "Fragment destroyed " + fragment + " (name: " + fragment.getClass() + ")"); } public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { + if (DBG) Log.d(TAG, "onPreferenceStartFragment"); Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras()); if (f instanceof SettingsPreferenceFragment) { ((SettingsPreferenceFragment) f).setOnStateListener(this); @@ -184,6 +185,13 @@ public class Settings extends Activity return true; } + @Override + public void onBackPressed() { + mBreadCrumbs.pop(); + mBreadCrumbs.update(); + super.onBackPressed(); + } + public static class TopLevelSettings extends PreferenceFragment { private IconPreferenceScreen mHighlightedPreference; @@ -198,6 +206,21 @@ public class Settings extends Activity updatePreferenceList(); } + @Override + public void onResume() { + super.onResume(); + + updateCallSettings(); + } + + private void updateCallSettings() { + Preference callSettings = findPreference(KEY_CALL_SETTINGS); + // Might have been removed in non-voice-capable devices + if (callSettings != null) { + callSettings.setEnabled(!AirplaneModeEnabler.isAirplaneModeOn(getActivity())); + } + } + private void updatePreferenceList() { final Activity activity = getActivity(); PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT); @@ -247,4 +270,91 @@ public class Settings extends Activity onPreferenceTreeClick(getPreferenceScreen(), first); } } + + public static class BreadCrumbs extends LinearLayout implements OnClickListener { + + private ArrayList mTitles = new ArrayList(); + private TextView mLevelUpTitle; + private TextView mCurrentLevelTitle; + private View mDivider; + private Activity mActivity; + + public BreadCrumbs(Context context) { + this(context, null); + } + + public BreadCrumbs(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void push(CharSequence title) { + if (mTitles.size() == 0 + || !TextUtils.equals(title, mTitles.get(mTitles.size() - 1))) { + mTitles.add(title); + update(); + } + } + + public void pop() { + if (mTitles.size() > 0) { + mTitles.remove(mTitles.size() - 1); + } + } + + public void pop(CharSequence title) { + if (mTitles.size() > 1) { + mTitles.remove(title); + } + } + + public void clear() { + mTitles.clear(); + } + + private void initNavViews() { + if (mLevelUpTitle == null) { + mLevelUpTitle = (TextView) findViewById(R.id.level_up_title); + mCurrentLevelTitle = (TextView) findViewById(R.id.level_current_title); + mDivider = findViewById(R.id.level_divider); + if (mLevelUpTitle != null) { + mLevelUpTitle.setOnClickListener(this); + } + if (mCurrentLevelTitle != null) { + mCurrentLevelTitle.setOnClickListener(this); + } + } + } + + public void update() { + initNavViews(); + if (mLevelUpTitle == null) return; + + final int titleCount = mTitles.size(); + if (titleCount > 1) { + mLevelUpTitle.setText(mTitles.get(titleCount - 2)); + mLevelUpTitle.setVisibility(VISIBLE); + mDivider.setVisibility(VISIBLE); + } else { + mLevelUpTitle.setVisibility(GONE); + mDivider.setVisibility(GONE); + } + if (titleCount > 0) { + mCurrentLevelTitle.setText(mTitles.get(titleCount - 1)); + } else { + mCurrentLevelTitle.setText(""); + } + } + + public void setActivity(Activity activity) { + mActivity = activity; + } + + public void onClick(View v) { + if (mActivity == null) + return; + if (v == mLevelUpTitle) { + mActivity.onBackPressed(); + } + } + } } diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java index d10fda38f08..bddfb2b7bb0 100644 --- a/src/com/android/settings/SettingsPreferenceFragment.java +++ b/src/com/android/settings/SettingsPreferenceFragment.java @@ -51,6 +51,8 @@ public class SettingsPreferenceFragment extends PreferenceFragment { private Button mNextButton; + private boolean mReportedCreation; + interface OnStateListener { void onCreated(SettingsPreferenceFragment fragment); @@ -65,8 +67,10 @@ public class SettingsPreferenceFragment extends PreferenceFragment { @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - if (mOnStateListener != null) { + if (mOnStateListener != null && !mReportedCreation) { mOnStateListener.onCreated(this); + // So that we don't report it on the way back to this fragment + mReportedCreation = true; } setupButtonBar();