From 574dc773ee85bb182d0b277f8ffdf6def9224972 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Tue, 14 Jan 2014 18:06:38 +0100 Subject: new: search suggestions for all search fields --- main/res/layout/search_activity.xml | 8 +-- main/src/cgeo/geocaching/DataStore.java | 81 ++++++++++++---------- main/src/cgeo/geocaching/SearchActivity.java | 62 ++++++++++++----- .../geocaching/search/AutoCompleteAdapter.java | 69 ++++++++++++++++++ 4 files changed, 161 insertions(+), 59 deletions(-) create mode 100644 main/src/cgeo/geocaching/search/AutoCompleteAdapter.java diff --git a/main/res/layout/search_activity.xml b/main/res/layout/search_activity.xml index 25f914b..28256f1 100644 --- a/main/res/layout/search_activity.xml +++ b/main/res/layout/search_activity.xml @@ -53,7 +53,7 @@ android:text="@string/search_address" /> - - - - ?) or reason > 0", - new String[]{Long.toString(timestamp)}, - null, - null, - "detailedupdate desc", - "100"); - - return getFirstColumn(cursor); - } catch (final Exception e) { - Log.e("DataStore.allDetailedThere", e); - return new String[0]; - } - } - public static boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) { init(); @@ -2931,21 +2909,6 @@ public class DataStore { return waypoints; } - public static String[] getTrackableCodes() { - init(); - - final Cursor cursor = database.query( - dbTableTrackables, - new String[] { "tbcode" }, - null, - null, - null, - null, - "updated DESC", - "100"); - return getFirstColumn(cursor); - } - /** * Extract the first column of the cursor rows and close the cursor. * @@ -3146,7 +3109,7 @@ public class DataStore { SearchManager.SUGGEST_COLUMN_QUERY }); try { - final String selectionArg = "%" + searchTerm + "%"; + final String selectionArg = getSuggestionArgument(searchTerm); findCaches(resultCursor, selectionArg); findTrackables(resultCursor, selectionArg); } catch (final Exception e) { @@ -3177,6 +3140,10 @@ public class DataStore { cursor.close(); } + private static String getSuggestionArgument(String input) { + return "%" + StringUtils.trim(input) + "%"; + } + private static void findTrackables(final MatrixCursor resultCursor, final String selectionArg) { Cursor cursor = database.query( dbTableTrackables, @@ -3199,4 +3166,42 @@ public class DataStore { cursor.close(); } + public static String[] getSuggestions(final String table, final String column, final String input) { + Cursor cursor = database.query( + true, + table, + new String[] { column }, + column + " LIKE ?", + new String[] { getSuggestionArgument(input) }, + null, + null, + column, + null); + return getFirstColumn(cursor); + } + + public static String[] getSuggestionsOwnerName(String input) { + return getSuggestions(dbTableCaches, "owner", input); + } + + public static String[] getSuggestionsTrackableCode(String input) { + return getSuggestions(dbTableTrackables, "tbcode", input); + } + + public static String[] getSuggestionsFinderName(String input) { + return getSuggestions(dbTableLogs, "author", input); + } + + public static String[] getSuggestionsGeocode(String input) { + return getSuggestions(dbTableCaches, "geocode", input); + } + + public static String[] getSuggestionsKeyword(String input) { + return getSuggestions(dbTableCaches, "name", input); + } + + public static String[] getSuggestionsAddress(String input) { + return getSuggestions(dbTableCaches, "location", input); + } + } diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java index a078fd2..3193a2e 100644 --- a/main/src/cgeo/geocaching/SearchActivity.java +++ b/main/src/cgeo/geocaching/SearchActivity.java @@ -10,6 +10,7 @@ import cgeo.geocaching.connector.capability.ISearchByGeocode; import cgeo.geocaching.connector.trackable.TrackableConnector; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; +import cgeo.geocaching.search.AutoCompleteAdapter; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.ui.dialog.CoordinatesInputDialog; import cgeo.geocaching.ui.dialog.Dialogs; @@ -17,6 +18,8 @@ import cgeo.geocaching.utils.EditUtils; import org.apache.commons.lang3.StringUtils; +import rx.util.functions.Func1; + import android.app.Activity; import android.app.SearchManager; import android.content.Intent; @@ -26,10 +29,8 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; -import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.Button; -import android.widget.EditText; import java.util.Locale; @@ -39,19 +40,19 @@ public class SearchActivity extends AbstractActivity { @InjectView(R.id.buttonLongitude) protected Button buttonLongitude; @InjectView(R.id.search_coordinates) protected Button buttonSearchCoords; - @InjectView(R.id.address) protected EditText addressEditText; + @InjectView(R.id.address) protected AutoCompleteTextView addressEditText; @InjectView(R.id.search_address) protected Button buttonSearchAddress; @InjectView(R.id.geocode) protected AutoCompleteTextView geocodeEditText; @InjectView(R.id.display_geocode) protected Button buttonSearchGeocode; - @InjectView(R.id.keyword) protected EditText keywordEditText; + @InjectView(R.id.keyword) protected AutoCompleteTextView keywordEditText; @InjectView(R.id.search_keyword) protected Button buttonSearchKeyword; - @InjectView(R.id.finder) protected EditText finderNameEditText; + @InjectView(R.id.finder) protected AutoCompleteTextView finderNameEditText; @InjectView(R.id.search_finder) protected Button buttonSearchFinder; - @InjectView(R.id.owner) protected EditText ownerNameEditText; + @InjectView(R.id.owner) protected AutoCompleteTextView ownerNameEditText; @InjectView(R.id.search_owner) protected Button buttonSearchOwner; @InjectView(R.id.trackable) protected AutoCompleteTextView trackableEditText; @@ -187,6 +188,12 @@ public class SearchActivity extends AbstractActivity { public void run() { findByAddressFn(); } + }, new Func1() { + + @Override + public String[] call(final String input) { + return DataStore.getSuggestionsAddress(input); + } }); setSearchAction(geocodeEditText, buttonSearchGeocode, new Runnable() { @@ -195,8 +202,13 @@ public class SearchActivity extends AbstractActivity { public void run() { findByGeocodeFn(); } + }, new Func1() { + + @Override + public String[] call(final String input) { + return DataStore.getSuggestionsGeocode(input); + } }); - addHistoryEntries(geocodeEditText, DataStore.getRecentGeocodesForSearch()); setSearchAction(keywordEditText, buttonSearchKeyword, new Runnable() { @@ -204,6 +216,12 @@ public class SearchActivity extends AbstractActivity { public void run() { findByKeywordFn(); } + }, new Func1() { + + @Override + public String[] call(final String input) { + return DataStore.getSuggestionsKeyword(input); + } }); setSearchAction(finderNameEditText, buttonSearchFinder, new Runnable() { @@ -212,6 +230,12 @@ public class SearchActivity extends AbstractActivity { public void run() { findByFinderFn(); } + }, new Func1() { + + @Override + public String[] call(final String input) { + return DataStore.getSuggestionsFinderName(input); + } }); setSearchAction(ownerNameEditText, buttonSearchOwner, new Runnable() { @@ -220,6 +244,12 @@ public class SearchActivity extends AbstractActivity { public void run() { findByOwnerFn(); } + }, new Func1() { + + @Override + public String[] call(final String input) { + return DataStore.getSuggestionsOwnerName(input); + } }); setSearchAction(trackableEditText, buttonSearchTrackable, new Runnable() { @@ -228,12 +258,16 @@ public class SearchActivity extends AbstractActivity { public void run() { findTrackableFn(); } + }, new Func1() { + + @Override + public String[] call(final String input) { + return DataStore.getSuggestionsTrackableCode(input); + } }); - addHistoryEntries(trackableEditText, DataStore.getTrackableCodes()); - disableSuggestions(trackableEditText); } - private static void setSearchAction(final EditText editText, final Button button, final Runnable runnable) { + private static void setSearchAction(final AutoCompleteTextView editText, final Button button, final Runnable runnable, final Func1 suggestionFunction) { EditUtils.setActionListener(editText, runnable); button.setOnClickListener(new View.OnClickListener() { @Override @@ -241,13 +275,7 @@ public class SearchActivity extends AbstractActivity { runnable.run(); } }); - } - - private void addHistoryEntries(final AutoCompleteTextView textView, final String[] entries) { - if (entries != null) { - final ArrayAdapter historyAdapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, entries); - textView.setAdapter(historyAdapter); - } + editText.setAdapter(new AutoCompleteAdapter(editText.getContext(), android.R.layout.simple_dropdown_item_1line, suggestionFunction)); } private class FindByCoordsAction implements OnClickListener { diff --git a/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java b/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java new file mode 100644 index 0000000..c314bbe --- /dev/null +++ b/main/src/cgeo/geocaching/search/AutoCompleteAdapter.java @@ -0,0 +1,69 @@ +package cgeo.geocaching.search; + +import org.apache.commons.lang3.StringUtils; + +import rx.util.functions.Func1; + +import android.content.Context; +import android.widget.ArrayAdapter; +import android.widget.Filter; + +/** + * The standard auto completion only matches user input at word boundaries. Therefore searching "est" will not match + * "test". This adapter matches everywhere. + * + */ +public class AutoCompleteAdapter extends ArrayAdapter { + + private String[] results; + private final Func1 suggestionFunction; + + public AutoCompleteAdapter(Context context, int textViewResourceId, final Func1 suggestionFunction) { + super(context, textViewResourceId); + this.suggestionFunction = suggestionFunction; + } + + @Override + public int getCount() { + return results.length; + } + + @Override + public String getItem(int index) { + return results[index]; + } + + @Override + public Filter getFilter() { + Filter filter = new Filter() { + + @Override + protected FilterResults performFiltering(CharSequence constraint) { + FilterResults filterResults = new FilterResults(); + if (constraint == null) { + return filterResults; + } + String trimmed = StringUtils.trim(constraint.toString()); + if (StringUtils.length(trimmed) >= 2) { + results = suggestionFunction.call(trimmed); + + // Assign the data to the FilterResults + filterResults.values = results; + filterResults.count = results.length; + } + return filterResults; + } + + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + if (results != null && results.count > 0) { + notifyDataSetChanged(); + } + else { + notifyDataSetInvalidated(); + } + } + }; + return filter; + } +} \ No newline at end of file -- cgit v1.1