Breaking search UI out of the contact list fragment
Change-Id: I6d0dbdccaf6a55b380984710989fe8a1f674d3fd
diff --git a/res/layout-finger/contacts_search_content.xml b/res/layout-finger/contacts_search_content.xml
index 680a891..480a8aa 100644
--- a/res/layout-finger/contacts_search_content.xml
+++ b/res/layout-finger/contacts_search_content.xml
@@ -26,9 +26,8 @@
<include android:id="@+id/searchView"
layout="@layout/search_bar"/>
- <view
- class="com.android.contacts.ContactEntryListView"
- android:id="@android:id/list"
+ <FrameLayout
+ android:id="@+id/list_container"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index a015d62..bfb6a96 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -35,6 +35,8 @@
import com.android.contacts.ui.ContactsPreferencesActivity;
import com.android.contacts.util.AccountSelectionUtil;
import com.android.contacts.widget.ContextMenuAdapter;
+import com.android.contacts.widget.SearchEditText;
+import com.android.contacts.widget.SearchEditText.OnFilterTextListener;
import android.accounts.Account;
import android.app.Activity;
@@ -81,33 +83,25 @@
private static final String TAG = "ContactsListActivity";
- private static final boolean ENABLE_ACTION_ICON_OVERLAYS = true;
-
- private static final String SHORTCUT_ACTION_KEY = "shortcutAction";
-
private static final int SUBACTIVITY_NEW_CONTACT = 1;
private static final int SUBACTIVITY_VIEW_CONTACT = 2;
private static final int SUBACTIVITY_DISPLAY_GROUP = 3;
private static final int SUBACTIVITY_SEARCH = 4;
protected static final int SUBACTIVITY_FILTER = 5;
- public static final String AUTHORITIES_FILTER_KEY = "authorities";
-
- static final String[] RAW_CONTACTS_PROJECTION = new String[] {
+ private static final String[] RAW_CONTACTS_PROJECTION = new String[] {
RawContacts._ID, //0
RawContacts.CONTACT_ID, //1
RawContacts.ACCOUNT_TYPE, //2
};
- static final String KEY_PICKER_MODE = "picker_mode";
-
private Uri mSelectedContactUri;
private ArrayList<Long> mWritableRawContactIds = new ArrayList<Long>();
private int mWritableSourcesCnt;
private int mReadOnlySourcesCnt;
- final String[] sLookupProjection = new String[] {
+ private final String[] sLookupProjection = new String[] {
Contacts.LOOKUP_KEY
};
private class DeleteClickListener implements DialogInterface.OnClickListener {
@@ -128,6 +122,7 @@
private boolean mSearchInitiated;
private ContactsRequest mRequest;
+ private SearchEditText mSearchEditText;
public ContactsListActivity() {
mIntentResolver = new ContactsIntentResolver(this);
@@ -164,11 +159,41 @@
onCreateFragment();
+ int listFragmentContainerId;
+ if (mRequest.isSearchMode()) {
+ setContentView(R.layout.contacts_search_content);
+ listFragmentContainerId = R.id.list_container;
+ setupSearchUI();
+ } else {
+ listFragmentContainerId = android.R.id.content;
+ }
FragmentTransaction transaction = openFragmentTransaction();
- transaction.add(mListFragment, android.R.id.content);
+ transaction.add(mListFragment, listFragmentContainerId);
transaction.commit();
}
+ private void setupSearchUI() {
+ mSearchEditText = (SearchEditText)findViewById(R.id.search_src_text);
+ mSearchEditText.setText(mRequest.getQueryString());
+ mSearchEditText.setOnFilterTextListener(new OnFilterTextListener() {
+ public void onFilterChange(String queryString) {
+ mListFragment.setQueryString(queryString);
+ }
+
+ public void onCancelSearch() {
+ finish();
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (mRequest.isSearchMode()) {
+ mSearchEditText.requestFocus();
+ }
+ }
+
/**
* Creates the fragment based on the current request.
*/
@@ -466,7 +491,7 @@
}
case R.id.menu_accounts: {
final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
- intent.putExtra(AUTHORITIES_FILTER_KEY, new String[] {
+ intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] {
ContactsContract.AUTHORITY
});
startActivity(intent);
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index c894ba7..1f8822e 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -22,8 +22,6 @@
import com.android.contacts.R;
import com.android.contacts.ui.ContactsPreferences;
import com.android.contacts.widget.ContextMenuAdapter;
-import com.android.contacts.widget.SearchEditText;
-import com.android.contacts.widget.SearchEditText.OnCloseListener;
import android.accounts.Account;
import android.accounts.AccountManager;
@@ -36,14 +34,12 @@
import android.content.Context;
import android.content.IContentService;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.os.RemoteException;
-import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.provider.ContactsContract.ProviderStatus;
@@ -51,7 +47,6 @@
import android.text.Editable;
import android.text.Html;
import android.text.TextUtils;
-import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -70,16 +65,13 @@
import android.widget.TextView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView.OnItemClickListener;
-import android.widget.TextView.OnEditorActionListener;
/**
* Common base class for various contact-related list fragments.
*/
public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter>
extends LoaderManagingFragment<Cursor>
- implements OnItemClickListener,
- OnScrollListener, TextWatcher, OnEditorActionListener, OnCloseListener,
- OnFocusChangeListener, OnTouchListener {
+ implements OnItemClickListener, OnScrollListener, OnFocusChangeListener, OnTouchListener {
private static final String TAG = "ContactEntryListFragment";
@@ -107,7 +99,6 @@
private ContextMenuAdapter mContextMenuAdapter;
private ContactPhotoLoader mPhotoLoader;
- private SearchEditText mSearchEditText;
private ContactListEmptyView mEmptyView;
private ProviderStatusLoader mProviderStatusLoader;
private ContactsPreferences mContactsPrefs;
@@ -132,6 +123,7 @@
return mAdapter;
}
+ @Override
public View getView() {
return mView;
}
@@ -221,7 +213,6 @@
public void setSearchMode(boolean flag) {
mSearchMode = flag;
- configureSearchEditText();
}
public boolean isSearchMode() {
@@ -230,7 +221,6 @@
public void setSearchResultsMode(boolean flag) {
mSearchResultsMode = flag;
- configureSearchEditText();
}
public boolean isSearchResultsMode() {
@@ -242,9 +232,12 @@
}
public void setQueryString(String queryString) {
- mQueryString = queryString;
- if (mAdapter != null) {
- mAdapter.setQueryString(queryString);
+ if (!TextUtils.equals(mQueryString, queryString)) {
+ mQueryString = queryString;
+ if (mAdapter != null) {
+ mAdapter.setQueryString(queryString);
+ reloadData();
+ }
}
}
@@ -324,7 +317,7 @@
mListState = savedState.getParcelable(LIST_STATE_KEY);
}
}
-
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -372,7 +365,6 @@
}
configurePhotoLoader();
- configureSearchEditText();
configureSearchResultText();
return mView;
}
@@ -401,15 +393,6 @@
}
}
}
- protected void configureSearchEditText() {
- if (isSearchMode() && mView != null) {
- mSearchEditText = (SearchEditText)mView.findViewById(R.id.search_src_text);
- mSearchEditText.setText(getQueryString());
- mSearchEditText.addTextChangedListener(this);
- mSearchEditText.setOnEditorActionListener(this);
- mSearchEditText.setOnCloseListener(this);
- }
- }
protected void configureAdapter() {
if (mAdapter != null) {
@@ -461,9 +444,6 @@
if (isPhotoLoaderEnabled()) {
mPhotoLoader.resume();
}
- if (isSearchMode()) {
- mSearchEditText.requestFocus();
- }
}
@Override
@@ -491,35 +471,6 @@
}
/**
- * Event handler for search UI.
- */
- public void afterTextChanged(Editable s) {
- String query = s.toString().trim();
- setQueryString(query);
- reloadData();
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- /**
- * Event handler for search UI.
- */
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- if (actionId == EditorInfo.IME_ACTION_DONE) {
- hideSoftKeyboard();
- if (TextUtils.isEmpty(getQueryString())) {
- finish();
- }
- return true;
- }
- return false;
- }
-
- /**
* Dismisses the soft keyboard when the list takes focus.
*/
public void onFocusChange(View view, boolean hasFocus) {
diff --git a/src/com/android/contacts/list/ContactsIntentResolver.java b/src/com/android/contacts/list/ContactsIntentResolver.java
index 62d56b5..8388daa 100644
--- a/src/com/android/contacts/list/ContactsIntentResolver.java
+++ b/src/com/android/contacts/list/ContactsIntentResolver.java
@@ -37,8 +37,8 @@
import android.util.Log;
/**
- * Maintains contact list configuration, which is a transient object that
- * deals with intents, saved instance configuration etc.
+ * Parses a Contacts intent, extracting all relevant parts and packaging them
+ * as a {@link ContactsRequest} object.
*/
@SuppressWarnings("deprecation")
public class ContactsIntentResolver {
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index 45380bc..13d60e1 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -124,9 +124,7 @@
@Override
protected View inflateView(LayoutInflater inflater, ViewGroup container) {
- if (isSearchMode()) {
- return inflater.inflate(R.layout.contacts_search_content, null);
- } else if (isSearchResultsMode()) {
+ if (isSearchResultsMode()) {
return inflater.inflate(R.layout.contacts_list_search_results, null);
} else {
return inflater.inflate(R.layout.contacts_list_content, null);
diff --git a/src/com/android/contacts/widget/SearchEditText.java b/src/com/android/contacts/widget/SearchEditText.java
index 1a50976..45001a5 100644
--- a/src/com/android/contacts/widget/SearchEditText.java
+++ b/src/com/android/contacts/widget/SearchEditText.java
@@ -18,31 +18,40 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.text.Editable;
import android.text.TextUtils;
+import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.KeyEvent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
/**
* A custom text editor that helps automatically dismiss the activity along with the soft
* keyboard.
*/
-public class SearchEditText extends EditText {
-
+public class SearchEditText extends EditText implements OnEditorActionListener, TextWatcher {
private boolean mMagnifyingGlassShown = true;
- private Drawable mMagnifyingGlass;
- private OnCloseListener mListener;
- public interface OnCloseListener {
- void onClose();
+ private Drawable mMagnifyingGlass;
+ private OnFilterTextListener mListener;
+
+ public interface OnFilterTextListener {
+ void onFilterChange(String queryString);
+ void onCancelSearch();
}
public SearchEditText(Context context, AttributeSet attrs) {
super(context, attrs);
+ addTextChangedListener(this);
+ setOnEditorActionListener(this);
mMagnifyingGlass = getCompoundDrawables()[2];
}
- public void setOnCloseListener(OnCloseListener listener) {
+ public void setOnFilterTextListener(OnFilterTextListener listener) {
this.mListener = listener;
}
@@ -71,9 +80,51 @@
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && TextUtils.isEmpty(getText()) && mListener != null) {
- mListener.onClose();
+ mListener.onCancelSearch();
return true;
}
return false;
}
+
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ /**
+ * Event handler for search UI.
+ */
+ public void afterTextChanged(Editable s) {
+ if (mListener != null) {
+ mListener.onFilterChange(trim(s));
+ }
+ }
+
+ private String trim(Editable s) {
+ return s.toString().trim();
+ }
+
+ /**
+ * Event handler for search UI.
+ */
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ hideSoftKeyboard();
+ if (TextUtils.isEmpty(trim(getText())) && mListener != null) {
+ mListener.onCancelSearch();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private void hideSoftKeyboard() {
+ // Hide soft keyboard, if visible
+ InputMethodManager inputMethodManager = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
+ }
+
}