summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/dashboard
diff options
context:
space:
mode:
authorFabrice Di Meglio <fdimeglio@google.com>2014-02-03 18:12:25 -0800
committerFabrice Di Meglio <fdimeglio@google.com>2014-03-03 14:46:17 -0800
commit6f0739a3d9a9eca1591ae6bada1dd4d1d92c0def (patch)
treea0257a0ab653412c44e477b43265f4d3de362746 /src/com/android/settings/dashboard
parent882e6cde603de53532f219b7f7548ceea641bc26 (diff)
downloadpackages_apps_Settings-6f0739a3d9a9eca1591ae6bada1dd4d1d92c0def.zip
packages_apps_Settings-6f0739a3d9a9eca1591ae6bada1dd4d1d92c0def.tar.gz
packages_apps_Settings-6f0739a3d9a9eca1591ae6bada1dd4d1d92c0def.tar.bz2
Add Search to the Settings App (initial release)
- add basic UI for search - build the search Index thru sqlite FTS4 (faster than FTS3) - create the search Index on the fly depending on the locale - re-index if there is a configuration change - re-index too if the Android build version has changed (usefull for an Android OTA or when a new Android version is pushed as we need to recompute the Index) - search thru "title" and "summary" Preference's data - group results in the same order of the Settings categories into the Drawer - rewrite "title" and/or "summary" if they are containing an hyphen "\u2011" - add Preference Keywords (only for the Settings App) in the Index and allow search on them (Wi-Fi network preference is used as an example) Known restrictions: - we cannot yet search for "dynamic settings" - ... nor we cannot search for settings coming from an external App (like the Phone App and its related settings that are surfacing into the Settings App). - will need a few other CLs to add more keywords (and have them translated) Change-Id: I017a4d6c433f28c257c08cacc1bed98c4c517039
Diffstat (limited to 'src/com/android/settings/dashboard')
-rw-r--r--src/com/android/settings/dashboard/DashboardSummary.java259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index f5b47ae..ce3b0c0 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -17,17 +17,97 @@
package com.android.settings.dashboard;
import android.app.Fragment;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.AsyncTask;
import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
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.ListView;
+import android.widget.TextView;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.indexer.Index;
public class DashboardSummary extends Fragment {
+ private static final String SAVE_KEY_QUERY = ":settings:query";
+
+ 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 void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (outState != null) {
+ outState.putString(SAVE_KEY_QUERY, mEditText.getText().toString());
+ }
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ if (savedInstanceState != null) {
+ final String query = savedInstanceState.getString(SAVE_KEY_QUERY);
+ if (query != null && !TextUtils.isEmpty(query)) {
+ mEditText.setText(query);
+ }
+ }
}
@Override
@@ -36,6 +116,185 @@ public class DashboardSummary extends Fragment {
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 fragmentName = cursor.getString(Index.COLUMN_INDEX_FRAGMENT_NAME);
+ final String fragmentTitle = cursor.getString(Index.COLUMN_INDEX_FRAGMENT_TITLE);
+
+ ((SettingsActivity) getActivity()).startPreferencePanel(fragmentName, null, 0,
+ fragmentTitle, null, 0);
+ }
+ });
+
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 void updateSearchResults() {
+ if (mUpdateSearchResultsTask != null) {
+ mUpdateSearchResultsTask.cancel(false);
+ mUpdateSearchResultsTask = null;
+ }
+ final String query = mEditText.getText().toString();
+ 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 SearchResult(String title, String summary, int iconResId) {
+ this.title = title;
+ this.summary = summary;
+ this.iconResId = iconResId;
+ }
+ }
+
+ private static class SearchResultsAdapter extends BaseAdapter {
+
+ private Cursor mCursor;
+ private LayoutInflater mInflater;
+ private boolean mDataValid;
+
+ public SearchResultsAdapter(Context context) {
+ mInflater = (LayoutInflater)context.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 int iconResId =
+ TextUtils.isEmpty(iconResStr) ? 0 : Integer.parseInt(iconResStr);
+ return new SearchResult(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) {
+ imageView.setImageResource(result.iconResId);
+ imageView.setBackgroundResource(R.color.background_search_result_icon);
+ } else {
+ imageView.setImageDrawable(null);
+ imageView.setBackgroundResource(R.drawable.empty_icon);
+ }
+
+ return view;
+ }
+ }
}