Breadcrumbs in the action bar for navigating up one level and showing current title.

Change-Id: I595e06549b888bd67c6dddd599a4cc77416c3a41
This commit is contained in:
Amith Yamasani
2010-09-12 08:17:50 -07:00
parent 60133dd036
commit b61cf51d85
6 changed files with 211 additions and 33 deletions

View File

@@ -49,7 +49,7 @@
<activity android:name="Settings" android:label="@string/settings_label"
android:taskAffinity="com.android.settings"
android:theme="@android:style/Theme.WithActionBar">
android:theme="@android:style/Theme.Holo">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.settings.SETTINGS" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,64 @@
<?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:padding="4dip"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<!-- ImageView
android:src="@drawable/ic_launcher_settings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dip"
android:layout_marginRight="4dip"
/-->
<view class="com.android.settings.Settings$BreadCrumbs"
android:id="@+id/bread_crumbs"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView android:id="@+id/level_up_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
style="?android:attr/textAppearanceMediumInverse"
/>
<ImageView
android:id="@+id/level_divider"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="4dip"
android:layout_marginBottom="4dip"
android:layout_marginLeft="12dip"
android:layout_marginRight="12dip"
android:src="@drawable/nav_divider"/>
<TextView android:id="@+id/level_current_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
style="?android:attr/textAppearanceMediumInverse"
/>
</view>
</LinearLayout>

View File

@@ -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<CharSequence> mTrail = new ArrayList<CharSequence>();
/*
@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) {
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<CharSequence> mTitles = new ArrayList<CharSequence>();
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();
}
}
}
}

View File

@@ -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();