summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
authorFabrice Di Meglio <fdimeglio@google.com>2014-03-21 19:24:43 -0700
committerFabrice Di Meglio <fdimeglio@google.com>2014-03-28 15:51:29 -0700
commitd25314d3305ed1a07b53991a978cd71219ef2a10 (patch)
tree797a75d9ff94055ee025294848e0154fae26f365 /src/com/android
parent5f3442af6f1d1141f8f4dff033d4176214281b81 (diff)
downloadpackages_apps_Settings-d25314d3305ed1a07b53991a978cd71219ef2a10.zip
packages_apps_Settings-d25314d3305ed1a07b53991a978cd71219ef2a10.tar.gz
packages_apps_Settings-d25314d3305ed1a07b53991a978cd71219ef2a10.tar.bz2
Settings - update for new UI (no more Drawer)
- follow the UX spec by no more using a Drawer - the Dashboard is now a Fragment that contains the list of Headers - the search results are also put into a Fragment that is replacing the initial one (Dashboard or other) when expanding the SearchView - use a SearchView for query input - when tapping on a Header or a Search Result, re-launch Settings as an Activity so that we are benefiting from the Activity stack for UP affordance and BACK button - manage UP affordance to show it only when needed - move some Actions to the Menu in the ActionBar for allowing space to the Search action and removing some clutter - fix an issue with the Index and WiFiEnabler and their cached Context that was not updated when there was a Configuration change - simplify the SettingsActivity code by extracting some inner classes Change-Id: I50b5f77bb44a7fade1886114dbbc820609a5e63d
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/settings/SettingsActivity.java974
-rw-r--r--src/com/android/settings/Utils.java3
-rwxr-xr-xsrc/com/android/settings/bluetooth/BluetoothSettings.java4
-rw-r--r--src/com/android/settings/dashboard/DashboardSummary.java322
-rw-r--r--src/com/android/settings/dashboard/Header.java177
-rw-r--r--src/com/android/settings/dashboard/HeaderAdapter.java275
-rw-r--r--src/com/android/settings/dashboard/NoHomeDialogFragment.java39
-rw-r--r--src/com/android/settings/dashboard/SearchResultsSummary.java331
-rw-r--r--src/com/android/settings/search/Index.java19
-rw-r--r--src/com/android/settings/wifi/WifiEnabler.java5
-rw-r--r--src/com/android/settings/wifi/WifiSettings.java11
11 files changed, 1105 insertions, 1055 deletions
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 0e6128c..c2b01cf 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -24,11 +24,10 @@ import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
+import android.app.SearchManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -38,17 +37,13 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Message;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -57,28 +52,20 @@ import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
-import android.support.v4.app.ActionBarDrawerToggle;
-import android.support.v4.widget.DrawerLayout;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.util.Xml;
-import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.ImageView;
import android.widget.ListView;
-import android.widget.Switch;
-import android.widget.TextView;
+import android.widget.SearchView;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
import com.android.settings.accessibility.AccessibilitySettings;
@@ -86,11 +73,15 @@ import com.android.settings.accessibility.CaptionPropertiesFragment;
import com.android.settings.accounts.AccountSyncSettings;
import com.android.settings.accounts.AuthenticatorHelper;
import com.android.settings.accounts.ManageAccountsSettings;
+import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.applications.ManageApplications;
import com.android.settings.applications.ProcessStatsUi;
-import com.android.settings.bluetooth.BluetoothEnabler;
import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.dashboard.DashboardSummary;
+import com.android.settings.dashboard.Header;
+import com.android.settings.dashboard.HeaderAdapter;
+import com.android.settings.dashboard.NoHomeDialogFragment;
+import com.android.settings.dashboard.SearchResultsSummary;
import com.android.settings.deviceinfo.Memory;
import com.android.settings.deviceinfo.UsbSettings;
import com.android.settings.fuelgauge.PowerUsageSummary;
@@ -109,7 +100,6 @@ import com.android.settings.users.UserSettings;
import com.android.settings.vpn2.VpnSettings;
import com.android.settings.wfd.WifiDisplaySettings;
import com.android.settings.wifi.AdvancedWifiSettings;
-import com.android.settings.wifi.WifiEnabler;
import com.android.settings.wifi.WifiSettings;
import com.android.settings.wifi.p2p.WifiP2pSettings;
import org.xmlpull.v1.XmlPullParser;
@@ -122,16 +112,22 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import static com.android.settings.dashboard.Header.HEADER_ID_UNDEFINED;
+
public class SettingsActivity extends Activity
implements PreferenceManager.OnPreferenceTreeClickListener,
PreferenceFragment.OnPreferenceStartFragmentCallback,
- ButtonBarHandler, OnAccountsUpdateListener, FragmentManager.OnBackStackChangedListener {
+ ButtonBarHandler, OnAccountsUpdateListener, FragmentManager.OnBackStackChangedListener,
+ SearchView.OnQueryTextListener, SearchView.OnCloseListener,
+ MenuItem.OnActionExpandListener {
private static final String LOG_TAG = "Settings";
// Constants for state save/restore
- private static final String SAVE_KEY_HEADERS_TAG = ":settings:headers";
- private static final String SAVE_KEY_CURRENT_HEADER_TAG = ":settings:cur_header";
+ private static final String SAVE_KEY_HEADERS = ":settings:headers";
+ private static final String SAVE_KEY_CURRENT_HEADER = ":settings:cur_header";
+ private static final String SAVE_KEY_SEARCH_MENU_EXPANDED = ":settings:search_menu_expanded";
+ private static final String SAVE_KEY_SEARCH_QUERY = ":settings:search_query";
/**
* When starting this activity, the invoking Intent can contain this extra
@@ -180,7 +176,7 @@ public class SettingsActivity extends Activity
* this extra can also be specify to supply the title to be shown for
* that fragment.
*/
- protected static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
+ public static final String EXTRA_SHOW_FRAGMENT_TITLE = ":settings:show_fragment_title";
private static final String META_DATA_KEY_HEADER_ID =
"com.android.settings.TOP_LEVEL_HEADER_ID";
@@ -193,13 +189,10 @@ public class SettingsActivity extends Activity
private static boolean sShowNoHomeNotice = false;
private String mFragmentClass;
- private int mTopLevelHeaderId;
- private Header mFirstHeader;
private Header mSelectedHeader;
private Header mCurrentHeader;
private CharSequence mInitialTitle;
- private Header mInitialHeader;
// Show only these settings for restricted users
private int[] SETTINGS_FOR_RESTRICTED = {
@@ -279,22 +272,19 @@ public class SettingsActivity extends Activity
TrustedCredentialsSettings.class.getName(),
PaymentSettings.class.getName(),
KeyboardLayoutPickerFragment.class.getName(),
- DashboardSummary.class.getName(),
- ZenModeSettings.class.getName()
+ ZenModeSettings.class.getName(),
+ NotificationSettings.class.getName(),
+ ChooseLockPassword.ChooseLockPasswordFragment.class.getName(),
+ ChooseLockPattern.ChooseLockPatternFragment.class.getName(),
+ InstalledAppDetails.class.getName()
};
private SharedPreferences mDevelopmentPreferences;
private SharedPreferences.OnSharedPreferenceChangeListener mDevelopmentPreferencesListener;
- // TODO: Update Call Settings based on airplane mode state.
-
- protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
-
private AuthenticatorHelper mAuthenticatorHelper;
private boolean mListeningToAccountUpdates;
- private Button mNextButton;
-
private boolean mBatteryPresent = true;
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
@@ -312,14 +302,21 @@ public class SettingsActivity extends Activity
}
};
+ private Button mNextButton;
+ private ActionBar mActionBar;
+
+ private SearchView mSearchView;
+ private MenuItem mSearchMenuItem;
+ private boolean mSearchMenuItemExpanded = false;
+ private boolean mIsShowingSearchResults = false;
+ private SearchResultsSummary mSearchResultsFragment;
+ private String mSearchQuery;
+
+ // Headers
+ protected HashMap<Integer, Integer> mHeaderIndexMap = new HashMap<Integer, Integer>();
private final ArrayList<Header> mHeaders = new ArrayList<Header>();
private HeaderAdapter mHeaderAdapter;
- private DrawerLayout mDrawerLayout;
- private ListView mDrawer;
- private ActionBarDrawerToggle mDrawerToggle;
- private ActionBar mActionBar;
-
private static final int MSG_BUILD_HEADERS = 1;
private Handler mHandler = new Handler() {
@Override
@@ -329,17 +326,13 @@ public class SettingsActivity extends Activity
mHeaders.clear();
onBuildHeaders(mHeaders);
mHeaderAdapter.notifyDataSetChanged();
- if (mCurrentHeader != null) {
- Header mappedHeader = findBestMatchingHeader(mCurrentHeader, mHeaders);
- if (mappedHeader != null) {
- setSelectedHeader(mappedHeader);
- }
- }
} break;
}
}
};
+ private boolean mNeedToRevertToInitialFragment = false;
+
@Override
public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
// Override the fragment title for Wallpaper settings
@@ -364,87 +357,6 @@ public class SettingsActivity extends Activity
return false;
}
- private class DrawerListener implements DrawerLayout.DrawerListener {
- @Override
- public void onDrawerOpened(View drawerView) {
- mDrawerToggle.onDrawerOpened(drawerView);
- }
-
- @Override
- public void onDrawerClosed(View drawerView) {
- mDrawerToggle.onDrawerClosed(drawerView);
- // Cannot process clicks when the App is finishing
- if (isFinishing() || mSelectedHeader == null) {
- return;
- }
- switchToHeader(mSelectedHeader, false, false);
- mSelectedHeader = null;
- }
-
- @Override
- public void onDrawerSlide(View drawerView, float slideOffset) {
- mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
- }
-
- @Override
- public void onDrawerStateChanged(int newState) {
- mDrawerToggle.onDrawerStateChanged(newState);
- }
- }
-
- private class DrawerItemClickListener implements ListView.OnItemClickListener {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- mDrawerLayout.closeDrawer(mDrawer);
- onListItemClick((ListView)parent, view, position, id);
- }
- }
-
- private Header findBestMatchingHeader(Header current, ArrayList<Header> from) {
- ArrayList<Header> matches = new ArrayList<Header>();
- for (int j=0; j<from.size(); j++) {
- Header oh = from.get(j);
- if (current == oh || (current.id != HEADER_ID_UNDEFINED && current.id == oh.id)) {
- // Must be this one.
- matches.clear();
- matches.add(oh);
- break;
- }
- if (current.fragment != null) {
- if (current.fragment.equals(oh.fragment)) {
- matches.add(oh);
- }
- } else if (current.intent != null) {
- if (current.intent.equals(oh.intent)) {
- matches.add(oh);
- }
- } else if (current.title != null) {
- if (current.title.equals(oh.title)) {
- matches.add(oh);
- }
- }
- }
- final int NM = matches.size();
- if (NM == 1) {
- return matches.get(0);
- } else if (NM > 1) {
- for (int j=0; j<NM; j++) {
- Header oh = matches.get(j);
- if (current.fragmentArguments != null &&
- current.fragmentArguments.equals(oh.fragmentArguments)) {
- return oh;
- }
- if (current.extras != null && current.extras.equals(oh.extras)) {
- return oh;
- }
- if (current.title != null && current.title.equals(oh.title)) {
- return oh;
- }
- }
- }
- return null;
- }
-
private void invalidateHeaders() {
if (!mHandler.hasMessages(MSG_BUILD_HEADERS)) {
mHandler.sendEmptyMessage(MSG_BUILD_HEADERS);
@@ -452,30 +364,48 @@ public class SettingsActivity extends Activity
}
@Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
-
- // Sync the toggle state after onRestoreInstanceState has occurred.
- mDrawerToggle.syncState();
- }
-
- @Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- mDrawerToggle.onConfigurationChanged(newConfig);
Index.getInstance(this).update();
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (mDrawerToggle.onOptionsItemSelected(item)) {
- return true;
+ protected void onStart() {
+ super.onStart();
+
+ if (mNeedToRevertToInitialFragment) {
+ revertToInitialFragment();
}
- return super.onOptionsItemSelected(item);
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.options_menu, menu);
+
+ // Cache the search query (can be overriden by the OnQueryTextListener)
+ final String query = mSearchQuery;
+
+ // Associate searchable configuration with the SearchView
+ SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+ mSearchView = (SearchView) menu.findItem(R.id.search).getActionView();
+
+ mSearchView.setOnQueryTextListener(this);
+ mSearchView.setOnCloseListener(this);
+
+ mSearchMenuItem = menu.findItem(R.id.search);
+ mSearchMenuItem.setOnActionExpandListener(this);
+
+ if (mSearchMenuItemExpanded) {
+ mSearchMenuItem.expandActionView();
+ }
+ mSearchView.setQuery(query, true /* submit */);
+
+ return true;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedState) {
if (getIntent().hasExtra(EXTRA_UI_OPTIONS)) {
getWindow().setUiOptions(getIntent().getIntExtra(EXTRA_UI_OPTIONS, 0));
}
@@ -489,78 +419,67 @@ public class SettingsActivity extends Activity
DevicePolicyManager dpm =
(DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
- mHeaderAdapter= new HeaderAdapter(this, mHeaders, mAuthenticatorHelper, dpm);
+ mHeaderAdapter = new HeaderAdapter(this, mHeaders, mAuthenticatorHelper, dpm);
mDevelopmentPreferences = getSharedPreferences(DevelopmentSettings.PREF_FILE,
Context.MODE_PRIVATE);
getMetaData();
- super.onCreate(savedInstanceState);
+ super.onCreate(savedState);
setContentView(R.layout.settings_main);
getFragmentManager().addOnBackStackChangedListener(this);
- mActionBar = getActionBar();
- mActionBar.setDisplayHomeAsUpEnabled(true);
- mActionBar.setHomeButtonEnabled(true);
+ boolean displayHomeAsUpEnabled = true;
- mDrawer = (ListView) findViewById(R.id.headers_drawer);
- mDrawer.setAdapter(mHeaderAdapter);
- mDrawer.setOnItemClickListener(new DrawerItemClickListener());
- mDrawer.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+ String initialFragmentName = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
+ Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
- mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
- mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
- R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);
+ if (savedState != null) {
+ mSearchMenuItemExpanded = savedState.getBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED);
+ mSearchQuery = savedState.getString(SAVE_KEY_SEARCH_QUERY);
- if (savedInstanceState != null) {
- // We are restarting from a previous saved state; used that to
+ // We are restarting from a previous saved state; used that to
// initialize, instead of starting fresh.
mInitialTitle = getTitle();
- ArrayList<Header> headers =
- savedInstanceState.getParcelableArrayList(SAVE_KEY_HEADERS_TAG);
+ ArrayList<Header> headers = savedState.getParcelableArrayList(SAVE_KEY_HEADERS);
if (headers != null) {
mHeaders.addAll(headers);
- int curHeader = savedInstanceState.getInt(SAVE_KEY_CURRENT_HEADER_TAG,
- (int) HEADER_ID_UNDEFINED);
- if (curHeader >= 0 && curHeader < mHeaders.size()) {
- setSelectedHeader(mHeaders.get(curHeader));
- mInitialHeader = mCurrentHeader;
- }
setTitleFromBackStack();
}
} else {
- String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
- Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
-
// We need to build the Headers in all cases
onBuildHeaders(mHeaders);
- if (initialFragment != null) {
- // If we are just showing a fragment, we want to run in
- // new fragment mode, but don't need to compute and show
- // the headers.
- final int initialTitleResId = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
- mInitialTitle = (initialTitleResId > 0) ? getText(initialTitleResId) : getTitle();
+ if (initialFragmentName != null) {
+ final ComponentName cn = getIntent().getComponent();
+ // No UP is we are launched thru a Settings shortcut
+ if (!cn.getClassName().equals(SubSettings.class.getName())) {
+ displayHomeAsUpEnabled = false;
+ }
+ final String initialTitle = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT_TITLE);
+ mInitialTitle = (initialTitle != null) ? initialTitle : getTitle();
setTitle(mInitialTitle);
- switchToHeaderInner(initialFragment, initialArguments, true, false, mInitialTitle);
- setSelectedHeaderById(mTopLevelHeaderId);
- mInitialHeader = mCurrentHeader;
+ switchToFragment( initialFragmentName, initialArguments, true, false,
+ mInitialTitle, false);
} else {
- // If there are headers, then at this point we need to show
- // them and, depending on the screen, we may also show in-line
- // the currently selected preference fragment.
+ // No UP if we are displaying the Headers
+ displayHomeAsUpEnabled = false;
if (mHeaders.size() > 0) {
- mInitialHeader = onGetInitialHeader();
- mInitialTitle = getHeaderTitle(mInitialHeader);
- switchToHeader(mInitialHeader, false, true);
+ mInitialTitle = getText(R.string.dashboard_title);
+ switchToFragment(DashboardSummary.class.getName(), null, false, false,
+ mInitialTitle, false);
}
}
}
+ mActionBar = getActionBar();
+ mActionBar.setHomeButtonEnabled(true);
+ mActionBar.setDisplayHomeAsUpEnabled(displayHomeAsUpEnabled);
+
// see if we should show Back/Next buttons
Intent intent = getIntent();
if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
@@ -615,39 +534,11 @@ public class SettingsActivity extends Activity
}
}
}
-
- if (!onIsHidingHeaders()) {
- highlightHeader(mTopLevelHeaderId);
- }
- }
-
- public Header onGetInitialHeader() {
- String fragmentClass = getStartingFragmentClass(super.getIntent());
- if (fragmentClass != null) {
- Header header = new Header();
- header.fragment = fragmentClass;
- header.title = getTitle();
- header.fragmentArguments = getIntent().getExtras();
- return header;
- }
-
- return mFirstHeader;
- }
-
- @Override
- public void onBackPressed() {
- if (mDrawerLayout.isDrawerOpen(mDrawer)) {
- mDrawerLayout.closeDrawer(mDrawer);
- return;
- }
- super.onBackPressed();
}
@Override
public void onBackStackChanged() {
- if (setTitleFromBackStack() == 0) {
- setSelectedHeaderById(mInitialHeader.id);
- }
+ setTitleFromBackStack();
}
private int setTitleFromBackStack() {
@@ -682,14 +573,16 @@ public class SettingsActivity extends Activity
super.onSaveInstanceState(outState);
if (mHeaders.size() > 0) {
- outState.putParcelableArrayList(SAVE_KEY_HEADERS_TAG, mHeaders);
+ outState.putParcelableArrayList(SAVE_KEY_HEADERS, mHeaders);
if (mCurrentHeader != null) {
int index = mHeaders.indexOf(mCurrentHeader);
if (index >= 0) {
- outState.putInt(SAVE_KEY_CURRENT_HEADER_TAG, index);
+ outState.putInt(SAVE_KEY_CURRENT_HEADER, index);
}
}
}
+ outState.putBoolean(SAVE_KEY_SEARCH_MENU_EXPANDED, mSearchMenuItem.isActionViewExpanded());
+ outState.putString(SAVE_KEY_SEARCH_QUERY, mSearchView.getQuery().toString());
}
@Override
@@ -709,16 +602,12 @@ public class SettingsActivity extends Activity
invalidateHeaders();
registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-
- mDrawerLayout.setDrawerListener(new DrawerListener());
}
@Override
public void onPause() {
super.onPause();
- mDrawerLayout.setDrawerListener(null);
-
unregisterReceiver(mBatteryInfoReceiver);
mHeaderAdapter.pause();
@@ -746,133 +635,24 @@ public class SettingsActivity extends Activity
return false;
}
- private CharSequence getHeaderTitle(Header header) {
- if (header == null || header.fragment == null) return getTitle();
- final CharSequence title;
- if (header.fragment.equals(DashboardSummary.class.getName())) {
- title = getResources().getString(R.string.settings_label);
- } else {
- title = header.getTitle(getResources());
- }
- return title;
- }
-
- private void setSelectedHeaderById(long headerId) {
- final int count = mHeaders.size();
- for (int n = 0; n < count; n++) {
- Header h = mHeaders.get(n);
- if (h.id == headerId) {
- setSelectedHeader(h);
- return;
- }
- }
- }
-
- /**
- * As the Headers can be rebuilt, their references can change, so use this method with caution!
- */
- private void setSelectedHeader(Header header) {
- if (header == null) {
- mCurrentHeader = null;
- return;
- }
- // Update selected Header into Drawer only if it is not "Add Account"
- if (header.id == R.id.account_add) {
- mDrawer.clearChoices();
- return;
- }
- mCurrentHeader = header;
- int index = mHeaders.indexOf(header);
- if (index >= 0) {
- mDrawer.setItemChecked(index, true);
- } else {
- mDrawer.clearChoices();
- }
- }
-
- private void highlightHeader(int id) {
- if (id != 0) {
- Integer index = mHeaderIndexMap.get(id);
- if (index != null) {
- mDrawer.setItemChecked(index, true);
- if (mDrawer.getVisibility() == View.VISIBLE) {
- mDrawer.smoothScrollToPosition(index);
- }
- }
- }
- }
-
/**
* When in two-pane mode, switch to the fragment pane to show the given
* preference fragment.
*
* @param header The new header to display.
- * @param validate true means that the fragment's Header needs to be validated.
- * @param initial true means that it is the initial Header.
*/
- private void switchToHeader(Header header, boolean validate, boolean initial) {
+ private void onHeaderClick(Header header) {
if (header == null) {
return;
}
- // For switching to another Header it should be a different one
- if (mCurrentHeader == null || header.id != mCurrentHeader.id) {
- if (header.fragment != null) {
- boolean addToBackStack;
- if (initial) {
- addToBackStack = false;
- } else {
- if (header.id != mInitialHeader.id) {
- addToBackStack = true;
- } else {
- addToBackStack = (mTopLevelHeaderId > 0);
- }
- }
- switchToHeaderInner(header.fragment, header.fragmentArguments, validate,
- addToBackStack, getHeaderTitle(header));
- setSelectedHeader(header);
- } else if (header.intent != null) {
- setSelectedHeader(header);
- startActivity(header.intent);
- } else {
- throw new IllegalStateException(
- "Can't switch to header that has no Fragment nor Intent");
- }
- }
- }
-
- /**
- * Switch to a specific Header with taking care of validation, Title and BackStack
- */
- private void switchToHeaderInner(String fragmentName, Bundle args, boolean validate,
- boolean addToBackStack, CharSequence title) {
- getFragmentManager().popBackStack(BACK_STACK_PREFS,
- FragmentManager.POP_BACK_STACK_INCLUSIVE);
- if (validate && !isValidFragment(fragmentName)) {
- throw new IllegalArgumentException("Invalid fragment for this activity: "
- + fragmentName);
- }
- Fragment f = Fragment.instantiate(this, fragmentName, args);
- FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.replace(R.id.prefs, f);
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
- if (addToBackStack) {
- transaction.addToBackStack(BACK_STACK_PREFS);
- }
- if (title != null) {
- transaction.setBreadCrumbTitle(title);
- }
- transaction.commitAllowingStateLoss();
- }
-
- @Override
- public void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
-
- // If it is not launched from history, then reset to top-level
- if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
- if (mDrawer != null) {
- mDrawer.setSelectionFromTop(0, 0);
- }
+ if (header.fragment != null) {
+ startWithFragment(header.fragment, header.fragmentArguments, null, 0,
+ header.getTitle(getResources()));
+ } else if (header.intent != null) {
+ startActivity(header.intent);
+ } else {
+ throw new IllegalStateException(
+ "Can't switch to header that has no Fragment nor Intent");
}
}
@@ -949,9 +729,8 @@ public class SettingsActivity extends Activity
* request code to be received with the resut.
*/
public void startPreferencePanel(String fragmentClass, Bundle args, int titleRes,
- CharSequence titleText, Fragment resultTo,
- int resultRequestCode) {
- startWithFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText);
+ CharSequence titleText, Fragment resultTo, int resultRequestCode) {
+ switchToFragment(fragmentClass, args, resultTo, resultRequestCode, titleRes, titleText);
}
/**
@@ -987,7 +766,7 @@ public class SettingsActivity extends Activity
}
/**
- * Start a new fragment.
+ * Start a new fragment. Used by #startPreferencePanel.
*
* @param fragmentName The name of the fragment to display.
* @param args Optional arguments to supply to the fragment.
@@ -1000,8 +779,8 @@ public class SettingsActivity extends Activity
* argument will be used as the title.
* @param titleText string to display for the title of.
*/
- private void startWithFragment(String fragmentName, Bundle args, Fragment resultTo,
- int resultRequestCode, int titleRes, CharSequence titleText) {
+ private void switchToFragment(String fragmentName, Bundle args, Fragment resultTo,
+ int resultRequestCode, int titleRes, CharSequence titleText) {
final CharSequence cs;
if (titleRes != 0) {
cs = getText(titleRes);
@@ -1022,6 +801,75 @@ public class SettingsActivity extends Activity
}
/**
+ * Switch to a specific Fragment with taking care of validation, Title and BackStack
+ */
+ private Fragment switchToFragment(String fragmentName, Bundle args, boolean validate,
+ boolean addToBackStack, CharSequence title, boolean withTransition) {
+ if (validate && !isValidFragment(fragmentName)) {
+ throw new IllegalArgumentException("Invalid fragment for this activity: "
+ + fragmentName);
+ }
+ Fragment f = Fragment.instantiate(this, fragmentName, args);
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.prefs, f);
+ if (withTransition) {
+ transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+ }
+ if (addToBackStack) {
+ transaction.addToBackStack(SettingsActivity.BACK_STACK_PREFS);
+ }
+ if (title != null) {
+ transaction.setBreadCrumbTitle(title);
+ }
+ transaction.commitAllowingStateLoss();
+ return f;
+ }
+
+ /**
+ * Start a new instance of this activity, showing only the given fragment.
+ * When launched in this mode, the given preference fragment will be instantiated and fill the
+ * entire activity.
+ *
+ * @param fragmentName The name of the fragment to display.
+ * @param args Optional arguments to supply to the fragment.
+ * @param resultTo Option fragment that should receive the result of
+ * the activity launch.
+ * @param resultRequestCode If resultTo is non-null, this is the request
+ * code in which to report the result.
+ * @param title String to display for the title of this set of preferences.
+ */
+ public void startWithFragment(String fragmentName, Bundle args,
+ Fragment resultTo, int resultRequestCode, CharSequence title) {
+ Intent intent = onBuildStartFragmentIntent(fragmentName, args, title);
+ if (resultTo == null) {
+ startActivity(intent);
+ } else {
+ resultTo.startActivityForResult(intent, resultRequestCode);
+ }
+ }
+
+ /**
+ * Build an Intent to launch a new activity showing the selected fragment.
+ * The implementation constructs an Intent that re-launches the current activity with the
+ * appropriate arguments to display the fragment.
+ *
+ * @param fragmentName The name of the fragment to display.
+ * @param args Optional arguments to supply to the fragment.
+ * @param title Optional title to show for this item.
+ * @return Returns an Intent that can be launched to display the given
+ * fragment.
+ */
+ public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args, CharSequence title) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(this, SubSettings.class);
+ intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
+ intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
+ intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE, title);
+ intent.putExtra(EXTRA_NO_HEADERS, true);
+ return intent;
+ }
+
+ /**
* Called when the activity needs its list of headers build.
*
* @param headers The list in which to place the headers.
@@ -1226,11 +1074,6 @@ public class SettingsActivity extends Activity
// Increment if the current one wasn't removed by the Utils code.
if (i < target.size() && target.get(i) == header) {
- // Hold on to the first header, when we need to reset to the top-level
- if (mFirstHeader == null &&
- HeaderAdapter.getHeaderType(header) != HeaderAdapter.HEADER_TYPE_CATEGORY) {
- mFirstHeader = header;
- }
mHeaderIndexMap.put(id, i);
i++;
}
@@ -1336,7 +1179,6 @@ public class SettingsActivity extends Activity
ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
PackageManager.GET_META_DATA);
if (ai == null || ai.metaData == null) return;
- mTopLevelHeaderId = ai.metaData.getInt(META_DATA_KEY_HEADER_ID);
mFragmentClass = ai.metaData.getString(META_DATA_KEY_FRAGMENT_CLASS);
} catch (NameNotFoundException nnfe) {
// No recovery
@@ -1353,261 +1195,19 @@ public class SettingsActivity extends Activity
return mNextButton;
}
- public static class NoHomeDialogFragment extends DialogFragment {
- public static void show(Activity parent) {
- final NoHomeDialogFragment dialog = new NoHomeDialogFragment();
- dialog.show(parent.getFragmentManager(), null);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- return new AlertDialog.Builder(getActivity())
- .setMessage(R.string.only_one_home_message)
- .setPositiveButton(android.R.string.ok, null)
- .create();
- }
- }
-
- private static class HeaderAdapter extends ArrayAdapter<Header> {
- static final int HEADER_TYPE_CATEGORY = 0;
- static final int HEADER_TYPE_NORMAL = 1;
- static final int HEADER_TYPE_SWITCH = 2;
- static final int HEADER_TYPE_BUTTON = 3;
- private static final int HEADER_TYPE_COUNT = HEADER_TYPE_BUTTON + 1;
-
- private final WifiEnabler mWifiEnabler;
- private final BluetoothEnabler mBluetoothEnabler;
- private AuthenticatorHelper mAuthHelper;
- private DevicePolicyManager mDevicePolicyManager;
-
- private static class HeaderViewHolder {
- ImageView mIcon;
- TextView mTitle;
- TextView mSummary;
- Switch mSwitch;
- ImageButton mButton;
- View mDivider;
- }
-
- private LayoutInflater mInflater;
-
- static int getHeaderType(Header header) {
- if (header.fragment == null && header.intent == null) {
- return HEADER_TYPE_CATEGORY;
- } else if (header.id == R.id.security_settings) {
- return HEADER_TYPE_BUTTON;
- } else {
- return HEADER_TYPE_NORMAL;
- }
- }
-
- @Override
- public int getItemViewType(int position) {
- Header header = getItem(position);
- return getHeaderType(header);
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false; // because of categories
- }
-
- @Override
- public boolean isEnabled(int position) {
- return getItemViewType(position) != HEADER_TYPE_CATEGORY;
- }
-
- @Override
- public int getViewTypeCount() {
- return HEADER_TYPE_COUNT;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- public HeaderAdapter(Context context, List<Header> objects,
- AuthenticatorHelper authenticatorHelper, DevicePolicyManager dpm) {
- super(context, 0, objects);
-
- mAuthHelper = authenticatorHelper;
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- // Temp Switches provided as placeholder until the adapter replaces these with actual
- // Switches inflated from their layouts. Must be done before adapter is set in super
- mWifiEnabler = new WifiEnabler(context, new Switch(context));
- mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
- mDevicePolicyManager = dpm;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- HeaderViewHolder holder;
- Header header = getItem(position);
- int headerType = getHeaderType(header);
- View view = null;
-
- if (convertView == null) {
- holder = new HeaderViewHolder();
- switch (headerType) {
- case HEADER_TYPE_CATEGORY:
- view = new TextView(getContext(), null,
- android.R.attr.listSeparatorTextViewStyle);
- holder.mTitle = (TextView) view;
- break;
-
- case HEADER_TYPE_SWITCH:
- view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
- false);
- holder.mIcon = (ImageView) view.findViewById(R.id.icon);
- holder.mTitle = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.mSummary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- holder.mSwitch = (Switch) view.findViewById(R.id.switchWidget);
- break;
-
- case HEADER_TYPE_BUTTON:
- view = mInflater.inflate(R.layout.preference_header_button_item, parent,
- false);
- holder.mIcon = (ImageView) view.findViewById(R.id.icon);
- holder.mTitle = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.mSummary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- holder.mButton = (ImageButton) view.findViewById(R.id.buttonWidget);
- holder.mDivider = view.findViewById(R.id.divider);
- break;
-
- case HEADER_TYPE_NORMAL:
- view = mInflater.inflate(
- R.layout.preference_header_item, parent,
- false);
- holder.mIcon = (ImageView) view.findViewById(R.id.icon);
- holder.mTitle = (TextView)
- view.findViewById(com.android.internal.R.id.title);
- holder.mSummary = (TextView)
- view.findViewById(com.android.internal.R.id.summary);
- break;
- }
- view.setTag(holder);
- } else {
- view = convertView;
- holder = (HeaderViewHolder) view.getTag();
- }
-
- // All view fields must be updated every time, because the view may be recycled
- switch (headerType) {
- case HEADER_TYPE_CATEGORY:
- holder.mTitle.setText(header.getTitle(getContext().getResources()));
- break;
-
- case HEADER_TYPE_SWITCH:
- // Would need a different treatment if the main menu had more switches
- if (header.id == R.id.wifi_settings) {
- mWifiEnabler.setSwitch(holder.mSwitch);
- } else {
- mBluetoothEnabler.setSwitch(holder.mSwitch);
- }
- updateCommonHeaderView(header, holder);
- break;
-
- case HEADER_TYPE_BUTTON:
- if (header.id == R.id.security_settings) {
- boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
- if (hasCert) {
- holder.mButton.setVisibility(View.VISIBLE);
- holder.mDivider.setVisibility(View.VISIBLE);
- boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
- if (isManaged) {
- holder.mButton.setImageResource(R.drawable.ic_settings_about);
- } else {
- holder.mButton.setImageResource(
- android.R.drawable.stat_notify_error);
- }
- holder.mButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(
- android.provider.Settings.ACTION_MONITORING_CERT_INFO);
- getContext().startActivity(intent);
- }
- });
- } else {
- holder.mButton.setVisibility(View.GONE);
- holder.mDivider.setVisibility(View.GONE);
- }
- }
- updateCommonHeaderView(header, holder);
- break;
-
- case HEADER_TYPE_NORMAL:
- updateCommonHeaderView(header, holder);
- break;
- }
-
- return view;
- }
-
- private void updateCommonHeaderView(Header header, HeaderViewHolder holder) {
- if (header.extras != null
- && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
- String accType = header.extras.getString(
- ManageAccountsSettings.KEY_ACCOUNT_TYPE);
- Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
- setHeaderIcon(holder, icon);
- } else {
- if (header.iconRes > 0) {
- holder.mIcon.setImageResource(header.iconRes);
- } else {
- holder.mIcon.setImageDrawable(null);
- }
- }
- if (holder.mIcon != null) {
- if (header.iconRes > 0) {
- holder.mIcon.setBackgroundResource(R.color.background_drawer_icon);
- } else {
- holder.mIcon.setBackground(null);
- }
- }
- holder.mTitle.setText(header.getTitle(getContext().getResources()));
- CharSequence summary = header.getSummary(getContext().getResources());
- if (!TextUtils.isEmpty(summary)) {
- holder.mSummary.setVisibility(View.VISIBLE);
- holder.mSummary.setText(summary);
- } else {
- holder.mSummary.setVisibility(View.GONE);
- }
- }
-
- private void setHeaderIcon(HeaderViewHolder holder, Drawable icon) {
- ViewGroup.LayoutParams lp = holder.mIcon.getLayoutParams();
- lp.width = getContext().getResources().getDimensionPixelSize(
- R.dimen.header_icon_width);
- lp.height = lp.width;
- holder.mIcon.setLayoutParams(lp);
- holder.mIcon.setImageDrawable(icon);
- }
-
- public void resume(Context context) {
- mWifiEnabler.resume();
- mBluetoothEnabler.resume(context);
- }
-
- public void pause() {
- mWifiEnabler.pause();
- mBluetoothEnabler.pause();
- }
+ public HeaderAdapter getHeaderAdapter() {
+ return mHeaderAdapter;
}
- private void onListItemClick(ListView l, View v, int position, long id) {
+ public void onListItemClick(ListView l, View v, int position, long id) {
if (!isResumed()) {
return;
}
Object item = mHeaderAdapter.getItem(position);
if (item instanceof Header) {
mSelectedHeader = (Header) item;
+ onHeaderClick(mSelectedHeader);
+ revertToInitialFragment();
}
}
@@ -1628,156 +1228,68 @@ public class SettingsActivity extends Activity
sShowNoHomeNotice = true;
}
- /**
- * Default value for {@link Header#id Header.id} indicating that no
- * identifier value is set. All other values (including those below -1)
- * are valid.
- */
- private static final long HEADER_ID_UNDEFINED = -1;
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ switchToSearchResultsFragmentIfNeeded();
+ mSearchQuery = query;
+ return mSearchResultsFragment.onQueryTextSubmit(query);
+ }
- /**
- * Description of a single Header item that the user can select.
- */
- static final class Header implements Parcelable {
- /**
- * Identifier for this header, to correlate with a new list when
- * it is updated. The default value is
- * {@link SettingsActivity#HEADER_ID_UNDEFINED}, meaning no id.
- * @attr ref android.R.styleable#PreferenceHeader_id
- */
- public long id = HEADER_ID_UNDEFINED;
-
- /**
- * Resource ID of title of the header that is shown to the user.
- * @attr ref android.R.styleable#PreferenceHeader_title
- */
- public int titleRes;
-
- /**
- * Title of the header that is shown to the user.
- * @attr ref android.R.styleable#PreferenceHeader_title
- */
- public CharSequence title;
-
- /**
- * Resource ID of optional summary describing what this header controls.
- * @attr ref android.R.styleable#PreferenceHeader_summary
- */
- public int summaryRes;
-
- /**
- * Optional summary describing what this header controls.
- * @attr ref android.R.styleable#PreferenceHeader_summary
- */
- public CharSequence summary;
-
- /**
- * Optional icon resource to show for this header.
- * @attr ref android.R.styleable#PreferenceHeader_icon
- */
- public int iconRes;
-
- /**
- * Full class name of the fragment to display when this header is
- * selected.
- * @attr ref android.R.styleable#PreferenceHeader_fragment
- */
- public String fragment;
-
- /**
- * Optional arguments to supply to the fragment when it is
- * instantiated.
- */
- public Bundle fragmentArguments;
-
- /**
- * Intent to launch when the preference is selected.
- */
- public Intent intent;
-
- /**
- * Optional additional data for use by subclasses of the activity
- */
- public Bundle extras;
-
- public Header() {
- // Empty
- }
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ mSearchQuery = newText;
+ return false;
+ }
- /**
- * Return the currently set title. If {@link #titleRes} is set,
- * this resource is loaded from <var>res</var> and returned. Otherwise
- * {@link #title} is returned.
- */
- public CharSequence getTitle(Resources res) {
- if (titleRes != 0) {
- return res.getText(titleRes);
- }
- return title;
- }
+ @Override
+ public boolean onClose() {
+ return false;
+ }
- /**
- * Return the currently set summary. If {@link #summaryRes} is set,
- * this resource is loaded from <var>res</var> and returned. Otherwise
- * {@link #summary} is returned.
- */
- public CharSequence getSummary(Resources res) {
- if (summaryRes != 0) {
- return res.getText(summaryRes);
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ if (item.getItemId() == mSearchMenuItem.getItemId()) {
+ if (mSearchResultsFragment == null) {
+ switchToSearchResultsFragmentIfNeeded();
}
- return summary;
- }
-
- @Override
- public int describeContents() {
- return 0;
}
+ return true;
+ }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(id);
- dest.writeInt(titleRes);
- TextUtils.writeToParcel(title, dest, flags);
- dest.writeInt(summaryRes);
- TextUtils.writeToParcel(summary, dest, flags);
- dest.writeInt(iconRes);
- dest.writeString(fragment);
- dest.writeBundle(fragmentArguments);
- if (intent != null) {
- dest.writeInt(1);
- intent.writeToParcel(dest, flags);
- } else {
- dest.writeInt(0);
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ if (item.getItemId() == mSearchMenuItem.getItemId()) {
+ if (mIsShowingSearchResults) {
+ revertToInitialFragment();
}
- dest.writeBundle(extras);
}
+ return true;
+ }
- public void readFromParcel(Parcel in) {
- id = in.readLong();
- titleRes = in.readInt();
- title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- summaryRes = in.readInt();
- summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- iconRes = in.readInt();
- fragment = in.readString();
- fragmentArguments = in.readBundle();
- if (in.readInt() != 0) {
- intent = Intent.CREATOR.createFromParcel(in);
+ private void switchToSearchResultsFragmentIfNeeded() {
+ if (!mIsShowingSearchResults) {
+ Fragment current = getFragmentManager().findFragmentById(R.id.prefs);
+ if (current != null && current instanceof SearchResultsSummary) {
+ mSearchResultsFragment = (SearchResultsSummary) current;
+ } else {
+ String title = getString(R.string.search_results_title);
+ mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
+ SearchResultsSummary.class.getName(), null, false, true, title, true);
}
- extras = in.readBundle();
+ mIsShowingSearchResults = true;
}
+ }
- Header(Parcel in) {
- readFromParcel(in);
- }
+ public void needToRevertToInitialFragment() {
+ mNeedToRevertToInitialFragment = true;
+ }
- public static final Creator<Header> CREATOR = new Creator<Header>() {
- public Header createFromParcel(Parcel source) {
- return new Header(source);
- }
- public Header[] newArray(int size) {
- return new Header[size];
- }
- };
+ private void revertToInitialFragment() {
+ mNeedToRevertToInitialFragment = false;
+ getFragmentManager().popBackStack(SettingsActivity.BACK_STACK_PREFS,
+ FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ mSearchResultsFragment = null;
+ mIsShowingSearchResults = false;
+ mSearchMenuItem.collapseActionView();
}
}
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index bf44835..1ae0829 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -55,6 +55,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TabWidget;
+import com.android.settings.dashboard.Header;
import java.io.IOException;
import java.io.InputStream;
@@ -237,7 +238,7 @@ public class Utils {
}
public static boolean updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context,
- List<SettingsActivity.Header> target, SettingsActivity.Header header) {
+ List<Header> target, Header header) {
Intent intent = header.intent;
if (intent != null) {
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index cc0371f..80f06b4 100755
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -129,7 +129,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
final SettingsActivity activity = (SettingsActivity) getActivity();
- if (!activity.onIsHidingHeaders()) {
+ if (activity.onIsHidingHeaders()) {
activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
ActionBar.DISPLAY_SHOW_CUSTOM);
activity.getActionBar().setCustomView(mSwitch, new ActionBar.LayoutParams(
@@ -198,7 +198,7 @@ public final class BluetoothSettings extends DeviceListPreferenceFragment implem
R.string.bluetooth_search_for_devices;
menu.add(Menu.NONE, MENU_ID_SCAN, 0, textId)
.setEnabled(bluetoothIsEnabled && !isDiscovering)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.add(Menu.NONE, MENU_ID_RENAME_DEVICE, 0, R.string.bluetooth_rename_device)
.setEnabled(bluetoothIsEnabled)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index b48e07e..f023dec 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -16,339 +16,35 @@
package com.android.settings.dashboard;
-import android.app.Fragment;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.graphics.drawable.Drawable;
-import android.os.AsyncTask;
+import android.app.ListFragment;
import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.EditText;
-import android.widget.ImageView;
+import android.widget.ListAdapter;
import android.widget.ListView;
-import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
-import com.android.settings.search.Index;
-
-import java.util.HashMap;
-
-public class DashboardSummary extends Fragment {
+public class DashboardSummary extends ListFragment {
private static final String LOG_TAG = "DashboardSummary";
- private EditText mEditText;
- private ListView mListView;
-
- private SearchResultsAdapter mAdapter;
- private Index mIndex;
- private UpdateSearchResultsTask mUpdateSearchResultsTask;
-
- /**
- * A basic AsyncTask for updating the query results cursor
- */
- private class UpdateSearchResultsTask extends AsyncTask<String, Void, Cursor> {
- @Override
- protected Cursor doInBackground(String... params) {
- return mIndex.search(params[0]);
- }
-
- @Override
- protected void onPostExecute(Cursor cursor) {
- if (!isCancelled()) {
- setCursor(cursor);
- } else if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mIndex = Index.getInstance(getActivity());
- mAdapter = new SearchResultsAdapter(getActivity());
- }
-
- @Override
- public void onStop() {
- super.onStop();
-
- clearResults();
- }
-
- @Override
- public void onStart() {
- super.onStart();
-
- updateSearchResults();
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.dashboard, container, false);
- mEditText = (EditText)view.findViewById(R.id.edittext_query);
- mEditText.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- updateSearchResults();
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- }
- });
- mEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- if (!hasFocus) {
- closeSoftKeyboard();
- }
- }
- });
-
- mListView = (ListView) view.findViewById(R.id.list_results);
- mListView.setAdapter(mAdapter);
- mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- closeSoftKeyboard();
-
- final Cursor cursor = mAdapter.mCursor;
- cursor.moveToPosition(position);
-
- final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME);
- final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE);
-
- final String action = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION);
-
- if (TextUtils.isEmpty(action)) {
- ((SettingsActivity) getActivity()).startPreferencePanel(className, null, 0,
- screenTitle, null, 0);
- } else {
- final Intent intent = new Intent(action);
-
- final String targetPackage = cursor.getString(
- Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
- final String targetClass = cursor.getString(
- Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS);
- if (!TextUtils.isEmpty(targetPackage) && !TextUtils.isEmpty(targetClass)) {
- final ComponentName component =
- new ComponentName(targetPackage, targetClass);
- intent.setComponent(component);
- }
+ ListView listView = (ListView) view.findViewById(android.R.id.list);
- getActivity().startActivity(intent);
- }
- }
- });
+ ListAdapter adapter = ((SettingsActivity) getActivity()).getHeaderAdapter();
+ listView.setAdapter(adapter);
return view;
}
- private void closeSoftKeyboard() {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null && imm.isActive(mEditText)) {
- imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
- }
- }
-
- private void clearResults() {
- if (mUpdateSearchResultsTask != null) {
- mUpdateSearchResultsTask.cancel(false);
- mUpdateSearchResultsTask = null;
- }
- setCursor(null);
- }
-
- private void setCursor(Cursor cursor) {
- Cursor oldCursor = mAdapter.swapCursor(cursor);
- if (oldCursor != null) {
- oldCursor.close();
- }
- }
-
- private String getFilteredQueryString() {
- final CharSequence query = mEditText.getText().toString();
- final StringBuilder filtered = new StringBuilder();
- for (int n = 0; n < query.length(); n++) {
- char c = query.charAt(n);
- if (!Character.isLetterOrDigit(c) && !Character.isSpaceChar(c)) {
- continue;
- }
- filtered.append(c);
- }
- return filtered.toString();
- }
-
- private void updateSearchResults() {
- if (mUpdateSearchResultsTask != null) {
- mUpdateSearchResultsTask.cancel(false);
- mUpdateSearchResultsTask = null;
- }
- final String query = getFilteredQueryString();
- if (TextUtils.isEmpty(query)) {
- setCursor(null);
- } else {
- mUpdateSearchResultsTask = new UpdateSearchResultsTask();
- mUpdateSearchResultsTask.execute(query);
- }
- }
-
- private static class SearchResult {
- public String title;
- public String summary;
- public int iconResId;
- public Context context;
-
- public SearchResult(Context context, String title, String summary, int iconResId) {
- this.context = context;
- this.title = title;
- this.summary = summary;
- this.iconResId = iconResId;
- }
- }
-
- private static class SearchResultsAdapter extends BaseAdapter {
-
- private Cursor mCursor;
- private LayoutInflater mInflater;
- private boolean mDataValid;
- private Context mContext;
- private HashMap<String, Context> mContextMap = new HashMap<String, Context>();
-
- public SearchResultsAdapter(Context context) {
- mContext = context;
- mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mDataValid = false;
- }
-
- public Cursor swapCursor(Cursor newCursor) {
- if (newCursor == mCursor) {
- return null;
- }
- Cursor oldCursor = mCursor;
- mCursor = newCursor;
- if (newCursor != null) {
- mDataValid = true;
- notifyDataSetChanged();
- } else {
- mDataValid = false;
- notifyDataSetInvalidated();
- }
- return oldCursor;
- }
-
- @Override
- public int getCount() {
- if (!mDataValid || mCursor == null || mCursor.isClosed()) return 0;
- return mCursor.getCount();
- }
-
- @Override
- public Object getItem(int position) {
- if (mDataValid && mCursor.moveToPosition(position)) {
- final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE);
- final String summary = mCursor.getString(Index.COLUMN_INDEX_SUMMARY);
- final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON);
- final String className = mCursor.getString(
- Index.COLUMN_INDEX_CLASS_NAME);
- final String packageName = mCursor.getString(
- Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
-
- Context packageContext;
- if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(packageName)) {
- packageContext = mContextMap.get(packageName);
- if (packageContext == null) {
- try {
- packageContext = mContext.createPackageContext(packageName, 0);
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(LOG_TAG, "Cannot create Context for package: " + packageName);
- return null;
- }
- mContextMap.put(packageName, packageContext);
- }
- } else {
- packageContext = mContext;
- }
- final int iconResId = TextUtils.isEmpty(iconResStr) ?
- R.drawable.empty_icon : Integer.parseInt(iconResStr);
- return new SearchResult(packageContext, title, summary, iconResId);
- }
- return null;
- }
-
- @Override
- public long getItemId(int position) {
- return 0;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (!mDataValid && convertView == null) {
- throw new IllegalStateException(
- "this should only be called when the cursor is valid");
- }
- if (!mCursor.moveToPosition(position)) {
- throw new IllegalStateException("couldn't move cursor to position " + position);
- }
-
- View view;
- TextView textTitle;
- TextView textSummary;
- ImageView imageView;
-
- if (convertView == null) {
- view = mInflater.inflate(R.layout.search_result, parent, false);
- } else {
- view = convertView;
- }
- textTitle = (TextView) view.findViewById(R.id.title);
- textSummary = (TextView) view.findViewById(R.id.summary);
- imageView = (ImageView) view.findViewById(R.id.icon);
-
- SearchResult result = (SearchResult) getItem(position);
-
- textTitle.setText(result.title);
- textSummary.setText(result.summary);
- if (result.iconResId != R.drawable.empty_icon) {
- final Context packageContext = result.context;
- final Drawable drawable;
- try {
- drawable = packageContext.getDrawable(result.iconResId);
- imageView.setImageDrawable(drawable);
- } catch (Resources.NotFoundException nfe) {
- // Not much we can do except logging
- Log.e(LOG_TAG, "Cannot load Drawable for " + result.title);
- }
- imageView.setBackgroundResource(R.color.background_search_result_icon);
- } else {
- imageView.setImageDrawable(null);
- imageView.setBackgroundResource(R.drawable.empty_icon);
- }
-
- return view;
- }
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ ((SettingsActivity) getActivity()).onListItemClick(l, v, position, id);
}
}
diff --git a/src/com/android/settings/dashboard/Header.java b/src/com/android/settings/dashboard/Header.java
new file mode 100644
index 0000000..86e55ac
--- /dev/null
+++ b/src/com/android/settings/dashboard/Header.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2014 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 com.android.settings.dashboard;
+
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * Description of a single Header item that the user can select.
+ */
+public class Header implements Parcelable {
+ /**
+ * Default value for {@link Header#id Header.id} indicating that no
+ * identifier value is set. All other values (including those below -1)
+ * are valid.
+ */
+ public static final long HEADER_ID_UNDEFINED = -1;
+
+ /**
+ * Identifier for this header, to correlate with a new list when
+ * it is updated. The default value is
+ * {@link Header#HEADER_ID_UNDEFINED}, meaning no id.
+ * @attr ref android.R.styleable#PreferenceHeader_id
+ */
+ public long id = HEADER_ID_UNDEFINED;
+
+ /**
+ * Resource ID of title of the header that is shown to the user.
+ * @attr ref android.R.styleable#PreferenceHeader_title
+ */
+ public int titleRes;
+
+ /**
+ * Title of the header that is shown to the user.
+ * @attr ref android.R.styleable#PreferenceHeader_title
+ */
+ public CharSequence title;
+
+ /**
+ * Resource ID of optional summary describing what this header controls.
+ * @attr ref android.R.styleable#PreferenceHeader_summary
+ */
+ public int summaryRes;
+
+ /**
+ * Optional summary describing what this header controls.
+ * @attr ref android.R.styleable#PreferenceHeader_summary
+ */
+ public CharSequence summary;
+
+ /**
+ * Optional icon resource to show for this header.
+ * @attr ref android.R.styleable#PreferenceHeader_icon
+ */
+ public int iconRes;
+
+ /**
+ * Full class name of the fragment to display when this header is
+ * selected.
+ * @attr ref android.R.styleable#PreferenceHeader_fragment
+ */
+ public String fragment;
+
+ /**
+ * Optional arguments to supply to the fragment when it is
+ * instantiated.
+ */
+ public Bundle fragmentArguments;
+
+ /**
+ * Intent to launch when the preference is selected.
+ */
+ public Intent intent;
+
+ /**
+ * Optional additional data for use by subclasses of the activity
+ */
+ public Bundle extras;
+
+ public Header() {
+ // Empty
+ }
+
+ /**
+ * Return the currently set title. If {@link #titleRes} is set,
+ * this resource is loaded from <var>res</var> and returned. Otherwise
+ * {@link #title} is returned.
+ */
+ public CharSequence getTitle(Resources res) {
+ if (titleRes != 0) {
+ return res.getText(titleRes);
+ }
+ return title;
+ }
+
+ /**
+ * Return the currently set summary. If {@link #summaryRes} is set,
+ * this resource is loaded from <var>res</var> and returned. Otherwise
+ * {@link #summary} is returned.
+ */
+ public CharSequence getSummary(Resources res) {
+ if (summaryRes != 0) {
+ return res.getText(summaryRes);
+ }
+ return summary;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(id);
+ dest.writeInt(titleRes);
+ TextUtils.writeToParcel(title, dest, flags);
+ dest.writeInt(summaryRes);
+ TextUtils.writeToParcel(summary, dest, flags);
+ dest.writeInt(iconRes);
+ dest.writeString(fragment);
+ dest.writeBundle(fragmentArguments);
+ if (intent != null) {
+ dest.writeInt(1);
+ intent.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeBundle(extras);
+ }
+
+ public void readFromParcel(Parcel in) {
+ id = in.readLong();
+ titleRes = in.readInt();
+ title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ summaryRes = in.readInt();
+ summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ iconRes = in.readInt();
+ fragment = in.readString();
+ fragmentArguments = in.readBundle();
+ if (in.readInt() != 0) {
+ intent = Intent.CREATOR.createFromParcel(in);
+ }
+ extras = in.readBundle();
+ }
+
+ Header(Parcel in) {
+ readFromParcel(in);
+ }
+
+ public static final Creator<Header> CREATOR = new Creator<Header>() {
+ public Header createFromParcel(Parcel source) {
+ return new Header(source);
+ }
+ public Header[] newArray(int size) {
+ return new Header[size];
+ }
+ };
+}
diff --git a/src/com/android/settings/dashboard/HeaderAdapter.java b/src/com/android/settings/dashboard/HeaderAdapter.java
new file mode 100644
index 0000000..720f83b
--- /dev/null
+++ b/src/com/android/settings/dashboard/HeaderAdapter.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2014 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 com.android.settings.dashboard;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.Switch;
+import android.widget.TextView;
+import com.android.settings.R;
+import com.android.settings.accounts.AuthenticatorHelper;
+import com.android.settings.accounts.ManageAccountsSettings;
+import com.android.settings.bluetooth.BluetoothEnabler;
+import com.android.settings.wifi.WifiEnabler;
+
+import java.util.List;
+
+/**
+ * A basic ArrayAdapter for dealing with the Headers
+ */
+public class HeaderAdapter extends ArrayAdapter<Header> {
+ public static final int HEADER_TYPE_CATEGORY = 0;
+ public static final int HEADER_TYPE_NORMAL = 1;
+ public static final int HEADER_TYPE_SWITCH = 2;
+ public static final int HEADER_TYPE_BUTTON = 3;
+
+ private static final int HEADER_TYPE_COUNT = HEADER_TYPE_BUTTON + 1;
+
+ private final WifiEnabler mWifiEnabler;
+ private final BluetoothEnabler mBluetoothEnabler;
+ private AuthenticatorHelper mAuthHelper;
+ private DevicePolicyManager mDevicePolicyManager;
+
+ private static class HeaderViewHolder {
+ ImageView mIcon;
+ TextView mTitle;
+ TextView mSummary;
+ Switch mSwitch;
+ ImageButton mButton;
+ View mDivider;
+ }
+
+ private LayoutInflater mInflater;
+
+ public static int getHeaderType(Header header) {
+ if (header.fragment == null && header.intent == null) {
+ return HEADER_TYPE_CATEGORY;
+ } else if (header.id == R.id.security_settings) {
+ return HEADER_TYPE_BUTTON;
+ } else {
+ return HEADER_TYPE_NORMAL;
+ }
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ Header header = getItem(position);
+ return getHeaderType(header);
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return false; // because of categories
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return getItemViewType(position) != HEADER_TYPE_CATEGORY;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return HEADER_TYPE_COUNT;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ public HeaderAdapter(Context context, List<Header> objects,
+ AuthenticatorHelper authenticatorHelper, DevicePolicyManager dpm) {
+ super(context, 0, objects);
+
+ mAuthHelper = authenticatorHelper;
+ mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ // Temp Switches provided as placeholder until the adapter replaces these with actual
+ // Switches inflated from their layouts. Must be done before adapter is set in super
+ mWifiEnabler = new WifiEnabler(context, new Switch(context));
+ mBluetoothEnabler = new BluetoothEnabler(context, new Switch(context));
+ mDevicePolicyManager = dpm;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ HeaderViewHolder holder;
+ Header header = getItem(position);
+ int headerType = getHeaderType(header);
+ View view = null;
+
+ if (convertView == null) {
+ holder = new HeaderViewHolder();
+ switch (headerType) {
+ case HEADER_TYPE_CATEGORY:
+ view = new TextView(getContext(), null,
+ android.R.attr.listSeparatorTextViewStyle);
+ holder.mTitle = (TextView) view;
+ break;
+
+ case HEADER_TYPE_SWITCH:
+ view = mInflater.inflate(R.layout.preference_header_switch_item, parent,
+ false);
+ holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+ holder.mTitle = (TextView)
+ view.findViewById(com.android.internal.R.id.title);
+ holder.mSummary = (TextView)
+ view.findViewById(com.android.internal.R.id.summary);
+ holder.mSwitch = (Switch) view.findViewById(R.id.switchWidget);
+ break;
+
+ case HEADER_TYPE_BUTTON:
+ view = mInflater.inflate(R.layout.preference_header_button_item, parent,
+ false);
+ holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+ holder.mTitle = (TextView)
+ view.findViewById(com.android.internal.R.id.title);
+ holder.mSummary = (TextView)
+ view.findViewById(com.android.internal.R.id.summary);
+ holder.mButton = (ImageButton) view.findViewById(R.id.buttonWidget);
+ holder.mDivider = view.findViewById(R.id.divider);
+ break;
+
+ case HEADER_TYPE_NORMAL:
+ view = mInflater.inflate(
+ R.layout.preference_header_item, parent,
+ false);
+ holder.mIcon = (ImageView) view.findViewById(R.id.icon);
+ holder.mTitle = (TextView)
+ view.findViewById(com.android.internal.R.id.title);
+ holder.mSummary = (TextView)
+ view.findViewById(com.android.internal.R.id.summary);
+ break;
+ }
+ view.setTag(holder);
+ } else {
+ view = convertView;
+ holder = (HeaderViewHolder) view.getTag();
+ }
+
+ // All view fields must be updated every time, because the view may be recycled
+ switch (headerType) {
+ case HEADER_TYPE_CATEGORY:
+ holder.mTitle.setText(header.getTitle(getContext().getResources()));
+ break;
+
+ case HEADER_TYPE_SWITCH:
+ // Would need a different treatment if the main menu had more switches
+ if (header.id == R.id.wifi_settings) {
+ mWifiEnabler.setSwitch(holder.mSwitch);
+ } else {
+ mBluetoothEnabler.setSwitch(holder.mSwitch);
+ }
+ updateCommonHeaderView(header, holder);
+ break;
+
+ case HEADER_TYPE_BUTTON:
+ if (header.id == R.id.security_settings) {
+ boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
+ if (hasCert) {
+ holder.mButton.setVisibility(View.VISIBLE);
+ holder.mDivider.setVisibility(View.VISIBLE);
+ boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
+ if (isManaged) {
+ holder.mButton.setImageResource(R.drawable.ic_settings_about);
+ } else {
+ holder.mButton.setImageResource(
+ android.R.drawable.stat_notify_error);
+ }
+ holder.mButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(
+ android.provider.Settings.ACTION_MONITORING_CERT_INFO);
+ getContext().startActivity(intent);
+ }
+ });
+ } else {
+ holder.mButton.setVisibility(View.GONE);
+ holder.mDivider.setVisibility(View.GONE);
+ }
+ }
+ updateCommonHeaderView(header, holder);
+ break;
+
+ case HEADER_TYPE_NORMAL:
+ updateCommonHeaderView(header, holder);
+ break;
+ }
+
+ return view;
+ }
+
+ private void updateCommonHeaderView(Header header, HeaderViewHolder holder) {
+ if (header.extras != null
+ && header.extras.containsKey(ManageAccountsSettings.KEY_ACCOUNT_TYPE)) {
+ String accType = header.extras.getString(
+ ManageAccountsSettings.KEY_ACCOUNT_TYPE);
+ Drawable icon = mAuthHelper.getDrawableForType(getContext(), accType);
+ setHeaderIcon(holder, icon);
+ } else {
+ if (header.iconRes > 0) {
+ holder.mIcon.setImageResource(header.iconRes);
+ } else {
+ holder.mIcon.setImageDrawable(null);
+ }
+ }
+ if (holder.mIcon != null) {
+ if (header.iconRes > 0) {
+ holder.mIcon.setBackgroundResource(R.color.background_drawer_icon);
+ } else {
+ holder.mIcon.setBackground(null);
+ }
+ }
+ holder.mTitle.setText(header.getTitle(getContext().getResources()));
+ CharSequence summary = header.getSummary(getContext().getResources());
+ if (!TextUtils.isEmpty(summary)) {
+ holder.mSummary.setVisibility(View.VISIBLE);
+ holder.mSummary.setText(summary);
+ } else {
+ holder.mSummary.setVisibility(View.GONE);
+ }
+ }
+
+ private void setHeaderIcon(HeaderViewHolder holder, Drawable icon) {
+ ViewGroup.LayoutParams lp = holder.mIcon.getLayoutParams();
+ lp.width = getContext().getResources().getDimensionPixelSize(
+ R.dimen.header_icon_width);
+ lp.height = lp.width;
+ holder.mIcon.setLayoutParams(lp);
+ holder.mIcon.setImageDrawable(icon);
+ }
+
+ public void resume(Context context) {
+ mWifiEnabler.resume(context);
+ mBluetoothEnabler.resume(context);
+ }
+
+ public void pause() {
+ mWifiEnabler.pause();
+ mBluetoothEnabler.pause();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/settings/dashboard/NoHomeDialogFragment.java b/src/com/android/settings/dashboard/NoHomeDialogFragment.java
new file mode 100644
index 0000000..a795cc9
--- /dev/null
+++ b/src/com/android/settings/dashboard/NoHomeDialogFragment.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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 com.android.settings.dashboard;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.os.Bundle;
+import com.android.settings.R;
+
+public class NoHomeDialogFragment extends DialogFragment {
+ public static void show(Activity parent) {
+ final NoHomeDialogFragment dialog = new NoHomeDialogFragment();
+ dialog.show(parent.getFragmentManager(), null);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(R.string.only_one_home_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .create();
+ }
+}
diff --git a/src/com/android/settings/dashboard/SearchResultsSummary.java b/src/com/android/settings/dashboard/SearchResultsSummary.java
new file mode 100644
index 0000000..992bb59
--- /dev/null
+++ b/src/com/android/settings/dashboard/SearchResultsSummary.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2014 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 com.android.settings.dashboard;
+
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.search.Index;
+
+import java.util.HashMap;
+
+public class SearchResultsSummary extends Fragment {
+
+ private static final String LOG_TAG = "SearchResultsSummary";
+
+ private ListView mListView;
+
+ private SearchResultsAdapter mAdapter;
+ private UpdateSearchResultsTask mUpdateSearchResultsTask;
+
+ /**
+ * A basic AsyncTask for updating the query results cursor
+ */
+ private class UpdateSearchResultsTask extends AsyncTask<String, Void, Cursor> {
+ @Override
+ protected Cursor doInBackground(String... params) {
+ return Index.getInstance(getActivity()).search(params[0]);
+ }
+
+ @Override
+ protected void onPostExecute(Cursor cursor) {
+ if (!isCancelled()) {
+ setCursor(cursor);
+ } else if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mAdapter = new SearchResultsAdapter(getActivity());
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+
+ clearResults();
+ }
+
+ @Override
+ public void onDestroy() {
+ mListView = null;
+ mAdapter = null;
+ mUpdateSearchResultsTask = null;
+
+ super.onDestroy();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ final View view = inflater.inflate(R.layout.search_results, container, false);
+
+ mListView = (ListView) view.findViewById(R.id.list_results);
+ mListView.setAdapter(mAdapter);
+ mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ final Cursor cursor = mAdapter.mCursor;
+ cursor.moveToPosition(position);
+
+ final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME);
+ final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE);
+
+ final String action = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION);
+
+ final SettingsActivity sa = (SettingsActivity) getActivity();
+
+ sa.needToRevertToInitialFragment();
+
+ if (TextUtils.isEmpty(action)) {
+ sa.startWithFragment(className, null, null, 0, screenTitle);
+ } else {
+ final Intent intent = new Intent(action);
+
+ final String targetPackage = cursor.getString(
+ Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
+ final String targetClass = cursor.getString(
+ Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS);
+ if (!TextUtils.isEmpty(targetPackage) && !TextUtils.isEmpty(targetClass)) {
+ final ComponentName component =
+ new ComponentName(targetPackage, targetClass);
+ intent.setComponent(component);
+ }
+
+ sa.startActivity(intent);
+ }
+ }
+ });
+
+ return view;
+ }
+
+ public boolean onQueryTextSubmit(String query) {
+ updateSearchResults(query);
+ return true;
+ }
+
+ public boolean onClose() {
+ clearResults();
+ return false;
+ }
+
+ private void clearResults() {
+ if (mUpdateSearchResultsTask != null) {
+ mUpdateSearchResultsTask.cancel(false);
+ mUpdateSearchResultsTask = null;
+ }
+ setCursor(null);
+ }
+
+ private void setCursor(Cursor cursor) {
+ if (mAdapter == null) {
+ return;
+ }
+ Cursor oldCursor = mAdapter.swapCursor(cursor);
+ if (oldCursor != null) {
+ oldCursor.close();
+ }
+ }
+
+ private String getFilteredQueryString(CharSequence query) {
+ final StringBuilder filtered = new StringBuilder();
+ for (int n = 0; n < query.length(); n++) {
+ char c = query.charAt(n);
+ if (!Character.isLetterOrDigit(c) && !Character.isSpaceChar(c)) {
+ continue;
+ }
+ filtered.append(c);
+ }
+ return filtered.toString();
+ }
+
+ private void updateSearchResults(CharSequence cs) {
+ if (mUpdateSearchResultsTask != null) {
+ mUpdateSearchResultsTask.cancel(false);
+ mUpdateSearchResultsTask = null;
+ }
+ final String query = getFilteredQueryString(cs);
+ if (TextUtils.isEmpty(query)) {
+ setCursor(null);
+ } else {
+ mUpdateSearchResultsTask = new UpdateSearchResultsTask();
+ mUpdateSearchResultsTask.execute(query);
+ }
+ }
+
+ private static class SearchResult {
+ public String title;
+ public String summary;
+ public int iconResId;
+ public Context context;
+
+ public SearchResult(Context context, String title, String summary, int iconResId) {
+ this.context = context;
+ this.title = title;
+ this.summary = summary;
+ this.iconResId = iconResId;
+ }
+ }
+
+ private static class SearchResultsAdapter extends BaseAdapter {
+
+ private Cursor mCursor;
+ private LayoutInflater mInflater;
+ private boolean mDataValid;
+ private Context mContext;
+ private HashMap<String, Context> mContextMap = new HashMap<String, Context>();
+
+ public SearchResultsAdapter(Context context) {
+ mContext = context;
+ mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mDataValid = false;
+ }
+
+ public Cursor swapCursor(Cursor newCursor) {
+ if (newCursor == mCursor) {
+ return null;
+ }
+ Cursor oldCursor = mCursor;
+ mCursor = newCursor;
+ if (newCursor != null) {
+ mDataValid = true;
+ notifyDataSetChanged();
+ } else {
+ mDataValid = false;
+ notifyDataSetInvalidated();
+ }
+ return oldCursor;
+ }
+
+ @Override
+ public int getCount() {
+ if (!mDataValid || mCursor == null || mCursor.isClosed()) return 0;
+ return mCursor.getCount();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ if (mDataValid && mCursor.moveToPosition(position)) {
+ final String title = mCursor.getString(Index.COLUMN_INDEX_TITLE);
+ final String summary = mCursor.getString(Index.COLUMN_INDEX_SUMMARY);
+ final String iconResStr = mCursor.getString(Index.COLUMN_INDEX_ICON);
+ final String className = mCursor.getString(
+ Index.COLUMN_INDEX_CLASS_NAME);
+ final String packageName = mCursor.getString(
+ Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE);
+
+ Context packageContext;
+ if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(packageName)) {
+ packageContext = mContextMap.get(packageName);
+ if (packageContext == null) {
+ try {
+ packageContext = mContext.createPackageContext(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(LOG_TAG, "Cannot create Context for package: " + packageName);
+ return null;
+ }
+ mContextMap.put(packageName, packageContext);
+ }
+ } else {
+ packageContext = mContext;
+ }
+ final int iconResId = TextUtils.isEmpty(iconResStr) ?
+ R.drawable.empty_icon : Integer.parseInt(iconResStr);
+ return new SearchResult(packageContext, title, summary, iconResId);
+ }
+ return null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (!mDataValid && convertView == null) {
+ throw new IllegalStateException(
+ "this should only be called when the cursor is valid");
+ }
+ if (!mCursor.moveToPosition(position)) {
+ throw new IllegalStateException("couldn't move cursor to position " + position);
+ }
+
+ View view;
+ TextView textTitle;
+ TextView textSummary;
+ ImageView imageView;
+
+ if (convertView == null) {
+ view = mInflater.inflate(R.layout.search_result_item, parent, false);
+ } else {
+ view = convertView;
+ }
+ textTitle = (TextView) view.findViewById(R.id.title);
+ textSummary = (TextView) view.findViewById(R.id.summary);
+ imageView = (ImageView) view.findViewById(R.id.icon);
+
+ SearchResult result = (SearchResult) getItem(position);
+
+ textTitle.setText(result.title);
+ textSummary.setText(result.summary);
+ if (result.iconResId != R.drawable.empty_icon) {
+ final Context packageContext = result.context;
+ final Drawable drawable;
+ try {
+ drawable = packageContext.getDrawable(result.iconResId);
+ imageView.setImageDrawable(drawable);
+ } catch (Resources.NotFoundException nfe) {
+ // Not much we can do except logging
+ Log.e(LOG_TAG, "Cannot load Drawable for " + result.title);
+ }
+ imageView.setBackgroundResource(R.color.background_search_result_icon);
+ } else {
+ imageView.setImageDrawable(null);
+ imageView.setBackgroundResource(R.drawable.empty_icon);
+ }
+
+ return view;
+ }
+ }
+}
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index 1a6bfb9..6ac5196 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -96,7 +96,7 @@ public class Index {
private static Index sInstance;
private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
private final UpdateData mDataToProcess = new UpdateData();
- private final Context mContext;
+ private Context mContext;
/**
* A private class to describe the update data for the Index database
@@ -124,6 +124,8 @@ public class Index {
public static Index getInstance(Context context) {
if (sInstance == null) {
sInstance = new Index(context);
+ } else {
+ sInstance.setContext(context);
}
return sInstance;
}
@@ -132,6 +134,10 @@ public class Index {
mContext = context;
}
+ public void setContext(Context context) {
+ mContext = context;
+ }
+
public boolean isAvailable() {
return mIsAvailable.get();
}
@@ -675,6 +681,17 @@ public class Index {
return (data != null) ? data.toString() : null;
}
+ private int getResId(Context context, AttributeSet set, int[] attrs, int resId) {
+ final TypedArray sa = context.obtainStyledAttributes(set, attrs);
+ final TypedValue tv = sa.peekValue(resId);
+
+ if (tv != null && tv.type == TypedValue.TYPE_STRING) {
+ return tv.resourceId;
+ } else {
+ return 0;
+ }
+ }
+
/**
* A private class for updating the Index database
*/
diff --git a/src/com/android/settings/wifi/WifiEnabler.java b/src/com/android/settings/wifi/WifiEnabler.java
index ad0ba56..e41429b 100644
--- a/src/com/android/settings/wifi/WifiEnabler.java
+++ b/src/com/android/settings/wifi/WifiEnabler.java
@@ -38,7 +38,7 @@ import com.android.settings.search.Index;
import java.util.concurrent.atomic.AtomicBoolean;
public class WifiEnabler implements CompoundButton.OnCheckedChangeListener {
- private final Context mContext;
+ private Context mContext;
private Switch mSwitch;
private AtomicBoolean mConnected = new AtomicBoolean(false);
@@ -77,7 +77,8 @@ public class WifiEnabler implements CompoundButton.OnCheckedChangeListener {
mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
}
- public void resume() {
+ public void resume(Context context) {
+ mContext = context;
// Wi-Fi state is sticky, so just let the receiver update UI
mContext.registerReceiver(mReceiver, mIntentFilter);
mSwitch.setOnCheckedChangeListener(this);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 667feb3..21fecd3 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -416,7 +416,7 @@ public class WifiSettings extends RestrictedSettingsFragment
if (activity instanceof SettingsActivity) {
SettingsActivity sa = (SettingsActivity) activity;
- addSwitch = !sa.onIsHidingHeaders();
+ addSwitch = sa.onIsHidingHeaders();
} else if (activity instanceof WifiPickerActivity) {
PreferenceActivity pa = (PreferenceActivity) activity;
addSwitch = pa.onIsHidingHeaders();
@@ -458,12 +458,13 @@ public class WifiSettings extends RestrictedSettingsFragment
@Override
public void onResume() {
+ final Activity activity = getActivity();
super.onResume();
if (mWifiEnabler != null) {
- mWifiEnabler.resume();
+ mWifiEnabler.resume(activity);
}
- getActivity().registerReceiver(mReceiver, mFilter);
+ activity.registerReceiver(mReceiver, mFilter);
updateAccessPoints();
}
@@ -497,11 +498,11 @@ public class WifiSettings extends RestrictedSettingsFragment
menu.add(Menu.NONE, MENU_ID_WPS_PBC, 0, R.string.wifi_menu_wps_pbc)
.setIcon(ta.getDrawable(1))
.setEnabled(wifiIsEnabled)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.add(Menu.NONE, MENU_ID_ADD_NETWORK, 0, R.string.wifi_add_network)
.setIcon(ta.getDrawable(0))
.setEnabled(wifiIsEnabled)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)
//.setIcon(R.drawable.ic_menu_scan_network)
.setEnabled(wifiIsEnabled)