Use PreferenceActivity and FragmentBreadCrumbs as they offer the same capabilities now.

Also fix: 2997438 and a similar bug in Tether Settings
Show + menu item for User Dictionary
This commit is contained in:
Amith Yamasani
2010-09-21 15:48:52 -07:00
parent 3a817f54f2
commit 02cf71a591
8 changed files with 282 additions and 505 deletions

View File

@@ -106,6 +106,8 @@ public class SecuritySettings extends SettingsPreferenceFragment
private LockPatternUtils mLockPatternUtils;
private ListPreference mLockAfter;
private SettingsObserver mSettingsObserver;
private final class SettingsObserver implements Observer {
public void update(Observable o, Object arg) {
updateToggles();
@@ -125,14 +127,24 @@ public class SecuritySettings extends SettingsPreferenceFragment
createPreferenceHierarchy();
updateToggles();
}
@Override
public void onStart() {
super.onStart();
// listen for Location Manager settings changes
Cursor settingsCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, null,
"(" + Settings.System.NAME + "=?)",
new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
null);
mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null);
mContentQueryMap.addObserver(new SettingsObserver());
mContentQueryMap.addObserver(mSettingsObserver = new SettingsObserver());
}
@Override
public void onStop() {
super.onStop();
mContentQueryMap.deleteObserver(mSettingsObserver);
}
private PreferenceScreen createPreferenceHierarchy() {

View File

@@ -16,354 +16,61 @@
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;
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 android.preference.PreferenceActivity;
import java.util.ArrayList;
import java.util.List;
/**
* Top-level settings activity to handle single pane and double pane UI layout.
*/
public class Settings extends Activity
implements PreferenceFragment.OnPreferenceStartFragmentCallback,
SettingsPreferenceFragment.OnStateListener,
public class Settings extends PreferenceActivity implements
SettingsPreferenceFragment.FragmentStarter {
private static final boolean DBG = false;
private static final String TAG = "Settings";
private static final String KEY_PARENT = "parent";
private static final String KEY_CALL_SETTINGS = "call_settings";
private static final String KEY_SYNC_SETTINGS = "sync_settings";
private static final String KEY_SEARCH_SETTINGS = "search_settings";
private static final String KEY_DOCK_SETTINGS = "dock_settings";
private static final String KEY_OPERATOR_SETTINGS = "operator_settings";
private static final String KEY_MANUFACTURER_SETTINGS = "manufacturer_settings";
public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
private static final String BACK_STACK_PREFS = ":settings:prefs";
private View mPrefsPane;
private View mMainPane;
private boolean mSinglePane;
private BreadCrumbs mBreadCrumbs;
// TODO: Update Call Settings based on airplane mode state.
/**
* Populate the activity with the top-level headers.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_top_level);
mPrefsPane = findViewById(R.id.prefs);
mMainPane = findViewById(R.id.top_level);
mSinglePane = mMainPane == null;
if (mSinglePane) mMainPane = mPrefsPane;
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.settings_headers, target);
final Intent intent = getIntent();
String initialFragment = intent.getStringExtra(EXTRA_SHOW_FRAGMENT);
Bundle initialArguments = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
updateHeaderList(target);
}
createActionBar();
if (mSinglePane) {
if (initialFragment != null) {
showFragment(initialFragment, initialArguments);
} else {
// Intent#getCompontent() lets us get Fragment name, even when the Intent is
// given via <activity-alias>.
//
// e.g. When we reach here via "ChildSetting" activity-alias,
// we should get the name here instead of targetActivity ("Settings").
if (intent.getComponent().getClassName().equals(this.getClass().getName())) {
showFragment(TopLevelSettings.class.getName(), null);
} else {
showFragment(intent.getComponent().getClassName(), intent.getExtras());
}
}
} else {
if (!intent.getComponent().getClassName().equals(this.getClass().getName())) {
if (showFragment(intent.getComponent().getClassName(), intent.getExtras())) {
mMainPane.setVisibility(View.GONE);
}
} else {
Fragment topLevel = getFragmentManager().findFragmentById(R.id.top_level);
if (topLevel != null) {
((TopLevelSettings) topLevel).selectFirst();
}
private void updateHeaderList(List<Header> target) {
int i = 0;
while (i < target.size()) {
Header header = target.get(i);
long id = header.id;
if (id == R.id.dock_settings) {
if (!needsDockSettings())
target.remove(header);
} else if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
} else if (id == R.id.call_settings) {
if (!Utils.isVoiceCapable(this))
target.remove(header);
}
if (target.get(i) == header)
i++;
}
}
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);
private boolean needsDockSettings() {
return getResources().getBoolean(R.bool.has_dock_settings);
}
boolean showFragment(Preference preference) {
if (mSinglePane) {
startWithFragment(preference.getFragment(), preference.getExtras());
return false;
} else {
mBreadCrumbs.clear();
return showFragment(preference.getFragment(), preference.getExtras());
}
}
private void startWithFragment(String fragmentName, Bundle args) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClass(this, getClass());
intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
startActivity(intent);
}
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 spf = (SettingsPreferenceFragment) f;
spf.setOnStateListener(this);
spf.setFragmentStarter(this);
}
mBreadCrumbs.clear();
getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
getFragmentManager().openTransaction().replace(R.id.prefs, f).commit();
return true;
}
private void addToBreadCrumbs(Fragment fragment) {
final CharSequence title = ((PreferenceFragment) fragment)
.getPreferenceScreen().getTitle();
if (mSinglePane) {
mBreadCrumbs.clear();
}
mBreadCrumbs.push(title);
}
private void removeFromBreadCrumbs(Fragment fragment) {
mBreadCrumbs.pop(((PreferenceFragment) fragment).getPreferenceScreen().getTitle());
mBreadCrumbs.update();
}
public void onCreated(SettingsPreferenceFragment fragment) {
if (DBG) Log.d(TAG, "Fragment created " + fragment);
addToBreadCrumbs(fragment);
}
public void onDestroyed(SettingsPreferenceFragment fragment) {
Log.d(TAG, "Fragment destroyed " + fragment + " (name: " + fragment.getClass() + ")");
}
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
if (DBG) Log.d(TAG, "onPreferenceStartFragment");
return startFragment(caller, pref.getFragment(), -1, pref.getExtras());
}
public boolean startFragment(
Fragment caller, String fragmentClass, int requestCode, Bundle extras) {
public boolean startFragment(Fragment caller, String fragmentClass, int requestCode,
Bundle extras) {
Fragment f = Fragment.instantiate(this, fragmentClass, extras);
caller.setTargetFragment(f, requestCode);
if (f instanceof SettingsPreferenceFragment) {
SettingsPreferenceFragment spf = (SettingsPreferenceFragment) f;
spf.setOnStateListener(this);
spf.setFragmentStarter(this);
}
getFragmentManager().openTransaction().replace(R.id.prefs, f)
.addToBackStack(BACK_STACK_PREFS).commit();
return true;
}
@Override
public void onBackPressed() {
mBreadCrumbs.pop();
mBreadCrumbs.update();
super.onBackPressed();
}
public static class TopLevelSettings extends PreferenceFragment {
private IconPreferenceScreen mHighlightedPreference;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.settings);
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);
Preference dockSettings = parent.findPreference(KEY_DOCK_SETTINGS);
if (activity.getResources().getBoolean(R.bool.has_dock_settings) == false
&& dockSettings != null) {
parent.removePreference(dockSettings);
}
Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(activity, parent,
KEY_OPERATOR_SETTINGS);
Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(activity, parent,
KEY_MANUFACTURER_SETTINGS);
Preference callSettings = parent.findPreference(KEY_CALL_SETTINGS);
if (!Utils.isVoiceCapable(activity) && callSettings != null) {
parent.removePreference(callSettings);
}
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
// If it is a fragment preference, replace the prefs pane in the 2 pane UI.
final String fragmentClass = preference.getFragment();
if (fragmentClass != null) {
boolean showed = ((Settings) getActivity()).showFragment(preference);
if (showed) {
highlight(preference);
}
return showed;
}
return false;
}
void highlight(Preference preference) {
if (mHighlightedPreference != null) {
mHighlightedPreference.setHighlighted(false);
}
mHighlightedPreference = (IconPreferenceScreen) preference;
mHighlightedPreference.setHighlighted(true);
}
void selectFirst() {
Preference first = getPreferenceScreen().getPreference(0);
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

@@ -35,7 +35,6 @@ import android.os.Environment;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.util.Log;
import android.webkit.WebView;
import java.io.InputStream;
@@ -220,8 +219,8 @@ public class TetherSettings extends SettingsPreferenceFragment {
}
@Override
public void onResume() {
super.onResume();
public void onStart() {
super.onStart();
final Activity activity = getActivity();
@@ -244,8 +243,8 @@ public class TetherSettings extends SettingsPreferenceFragment {
}
@Override
public void onPause() {
super.onPause();
public void onStop() {
super.onStop();
getActivity().unregisterReceiver(mTetherChangeReceiver);
mTetherChangeReceiver = null;
mWifiApEnabler.pause();

View File

@@ -37,9 +37,9 @@ import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.preference.Preference.OnPreferenceClickListener;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.speech.tts.TextToSpeech;
@@ -126,6 +126,7 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
mDefaultLocVariant = currentLocale.getVariant();
mTts = new TextToSpeech(activity, this);
initClickers();
}
@@ -136,7 +137,6 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
// whenever we return to this screen, we don't know the state of the
// system, so we have to recheck that we can play the demo, or it must be disabled.
// TODO make the TTS service listen to "changes in the system", i.e. sd card un/mount
initClickers();
updateWidgetState();
checkVoiceData();
}
@@ -357,7 +357,6 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
mTts.setLanguage(new Locale(mDefaultLanguage, mDefaultCountry, mDefaultLocVariant));
mTts.setSpeechRate(mDefaultRate/100.0f);
initDefaultSettings();
initClickers();
updateWidgetState();
checkVoiceData();
mTtsStarted = true;

View File

@@ -31,7 +31,6 @@ import android.provider.UserDictionary;
import android.text.InputType;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -39,7 +38,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AlphabetIndexer;
import android.widget.EditText;
import android.widget.ListAdapter;
@@ -47,6 +46,7 @@ import android.widget.ListView;
import android.widget.SectionIndexer;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import java.util.Locale;
@@ -198,8 +198,10 @@ public class UserDictionarySettings extends ListFragment implements DialogCreata
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
MenuItem actionItem =
menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
.setIcon(R.drawable.ic_menu_add);
actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
@Override

View File

@@ -20,8 +20,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.drawable.Drawable;
@@ -29,9 +29,9 @@ import android.os.Bundle;
import android.os.SystemProperties;
import android.preference.Preference;
import android.preference.PreferenceGroup;
import android.preference.PreferenceActivity.Header;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import java.util.List;
@@ -203,6 +203,66 @@ public class Utils {
return false;
}
public static boolean updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context,
List<Header> target, Header header) {
Intent intent = header.intent;
if (intent != null) {
// Find the activity that is in the system image
PackageManager pm = context.getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
int listSize = list.size();
for (int i = 0; i < listSize; i++) {
ResolveInfo resolveInfo = list.get(i);
if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
!= 0) {
Drawable icon = null;
String title = null;
String summary = null;
// Get the activity's meta-data
try {
Resources res = pm.getResourcesForApplication(
resolveInfo.activityInfo.packageName);
Bundle metaData = resolveInfo.activityInfo.metaData;
if (res != null && metaData != null) {
icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
}
} catch (NameNotFoundException e) {
// Ignore
} catch (NotFoundException e) {
// Ignore
}
// Set the preference title to the activity's label if no
// meta-data is found
if (TextUtils.isEmpty(title)) {
title = resolveInfo.loadLabel(pm).toString();
}
// Set icon, title and summary for the preference
// TODO:
//header.icon = icon;
header.title = title;
header.summary = summary;
// Replace the intent with this specific activity
header.intent = new Intent().setClassName(resolveInfo.activityInfo.packageName,
resolveInfo.activityInfo.name);
return true;
}
}
}
// Did not find a matching activity, so remove the preference
if (target.remove(header)) System.err.println("Removed " + header.id);
return false;
}
/**
* Returns true if Monkey is running.
*/