I am very new to using SearchView
. I need a functionality where I have an ActionBar
for which I have Search
. When I click on Search, the Suggestions should be displayed in a List below the Search field.
What I have done so far :
Added search in menu.xml and wrote the code in onCreateOptionsMenu()
where I initialize the SearchView and setSuggestionsAdapter
also implement setOnQueryTextListener
.
Result: I enter the app, click on search Icon, it shows the suggestions. I type a letter it sorts out the matched ones. I type 2nd letter it shows no suggestions. Also I close the searchview and open it again, the Keyboard is opened, but the Suggestions in List is not shown.
What I need : Filter according to user entered characters. Even if it's more than one character. Always show suggestions either default one with all list items or the ones that's sorted when user type.
I have seen in the SearchView class of Android, they are setting the text to empty and also dismissing the Suggestions. But I don't want this.
I am stuck here and don't know how to proceed. Please help me. Here is my Adapter Code:
public class ExampleAdapter extends CursorAdapter implements Filterable {
private ArrayList<String> items;
private ArrayList<String> orig;
public ExampleAdapter(Context context, Cursor cursor,
ArrayList<String> items) {
super(context, cursor, false);
this.items = new ArrayList<String>();
this.items = items;
orig = new ArrayList<String>();
orig.addAll(items);
}
@Override
public int getCount() {
return items.size();
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString().toLowerCase();
FilterResults result = new FilterResults();
if (constraint != null
&& constraint.toString().length() > 0) {
List<String> founded = new ArrayList<String>();
for (int i = 0, l = orig.size(); i < l; i++) {
if (orig.get(i)
.toString()
.toLowerCase()
.startsWith(
constraint.toString().toLowerCase()))
founded.add(orig.get(i));
}
result.values = founded;
result.count = founded.size();
} else {
synchronized (this) {
result.values = orig;
result.count = orig.size();
}
}
return result;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
items.clear();
items = new ArrayList<String>();
items = (ArrayList<String>) results.values;
notifyDataSetChanged();
}
};
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.textView.setText(items.get(cursor.getPosition()));
}
public class ViewHolder {
public TextView textView;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ViewHolder holder = new ViewHolder();
View v = null;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.item, parent, false);
holder.textView = (TextView) v.findViewById(R.id.text);
v.setTag(holder);
return v;
}
}
Code in my Activity related to Menu where I have searchview :
private String[] columns = new String[] { "_id", "text" };
private SearchView searchView;
private SearchManager manager;
private ExampleAdapter aptr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
setSearchTextColour(searchView);
setSearchIcons(searchView);
searchView.setQueryHint(Html.fromHtml("<font color = #ffffff>"
+ getResources().getString(R.string.search_store) + "</font>"));
searchView.setSearchableInfo(manager
.getSearchableInfo(getComponentName()));
Object[] temp = new Object[] { 0, "default" };
final MatrixCursor cursor = new MatrixCursor(columns);
for (int i = 0; i < alStoreNames.size(); i++) {
temp[0] = i;
temp[1] = alStoreNames.get(i);
cursor.addRow(temp);
}
aptr = new ExampleAdapter(MainActivity.this, cursor, alStoreNames);
searchView.setSuggestionsAdapter(aptr);
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String arg0) {
if (!TextUtils.isEmpty(arg0)) {
aptr.getFilter().filter(arg0.toString());
}
return true;
}
@Override
public boolean onQueryTextChange(String arg0) {
return false;
}
});
searchView.setOnSuggestionListener(new OnSuggestionListener() {
@Override
public boolean onSuggestionSelect(int arg0) {
return false;
}
@Override
public boolean onSuggestionClick(int position) {
String suggestion = getSuggestion(position);
db.openDatabase();
String studentId = db.getStudentIdFromName(suggestion);
String studentImg = db.getStudentImgFromName(suggestion);
db.closeDatabase();
Log.e("Sp", " On Click name -> " + aptr.getItem(position).toString() + " : "
+ aptr.getCursor().getString(0) + " : " + suggestion);
Intent i = new Intent(MainActivity.this,
ExampleActivity.class);
i.putExtra("studentId", studentId);
i.putExtra("studentName", suggestion);
i.putExtra("studentImg", studentImg);
startActivity(i);
return true;
}
});
return true;
}
private String getSuggestion(int position) {
Cursor cursor = (Cursor) searchView.getSuggestionsAdapter().getItem(
position);
String suggest1 = cursor.getString(cursor.getColumnIndex("text"));
return suggest1;
}
private void setSearchTextColour(SearchView searchView) {
Field qTextField;
try {
qTextField = SearchView.class.getDeclaredField("mQueryTextView");
qTextField.setAccessible(true);
SearchAutoComplete searchPlate = (SearchAutoComplete) qTextField
.get(searchView);
searchPlate.setTextColor(getResources().getColor(R.color.white));
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private void setSearchIcons(SearchView searchView) {
try {
Field searchField = SearchView.class
.getDeclaredField("mCloseButton");
searchField.setAccessible(true);
ImageView closeBtn = (ImageView) searchField.get(searchView);
closeBtn.setImageResource(R.drawable.close);
Field searchField1 = SearchView.class
.getDeclaredField("mSearchButton");
searchField1.setAccessible(true);
ImageView searchButton = (ImageView) searchField1.get(searchView);
searchButton.setImageResource(R.drawable.ic_action_search);
} catch (NoSuchFieldException e) {
Log.e("SearchView", e.getMessage(), e);
} catch (IllegalAccessException e) {
Log.e("SearchView", e.getMessage(), e);
}
}
It seems to me that part of the problem is in the absence of the getItem() method.
If you look at the cursor adapter source code the getItem() will get the data from the cursor, and not from your filtered list, you want it to get the data from your filtered list!
Try this:
@Override
public Object getItem(int position) {
if (position < items.size()) {
return items.get(position);
} else {
return null;
}
}
i forgot to add, you also need to change this:
private String getSuggestion(int position) {
String suggest1 = (String) searchView.getSuggestionsAdapter().getItem(position);
return suggest1;
}
And to close everything,first add this to createOptions menu:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setIconifiedByDefault(true); //this line
...
then add this to onSuggestionClick:
@Override
public boolean onSuggestionClick(int position) {
String suggestion = getSuggestion(position);
db.openDatabase();
String studentId = db.getStudentIdFromName(suggestion);
String studentImg = db.getStudentImgFromName(suggestion);
db.closeDatabase();
Log.e("Sp", " On Click name -> " + aptr.getItem(position).toString() + " : "
+ aptr.getCursor().getString(0) + " : " + suggestion);
searchView.setIconified(true);//this line
Intent i = new Intent(MainActivity.this,ExampleActivity.class);
i.putExtra("studentId", studentId);
i.putExtra("studentName", suggestion);
i.putExtra("studentImg", studentImg);
startActivity(i);
return true;
}
A bit of an explanation. When you call setIconified it will either clear the text of your searchView or collapse it, depending on the default state. What we did there was set the default state to iconified so when we call the setIconified method it will clear the text and collapse the view!
Hello I found some problems with your code.
please try my way.
replace publishResults of ExampleAdapter
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
items.clear();
// items = new ArrayList<String>();
//items = (ArrayList<String>) results.values;
items.addAll((ArrayList<String>) results.values);
notifyDataSetChanged();
}
AND
searchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String arg0) {
if (!TextUtils.isEmpty(arg0)) {
aptr.getFilter().filter(arg0.toString());
}
return true;
}
@Override
public boolean onQueryTextChange(String arg0) {
if (!TextUtils.isEmpty(arg0)) {
aptr.getFilter().filter(arg0.toString());
return true;
}
return false;
}
});
Try to pass search value to filter even is empty :
@Override
public boolean onQueryTextSubmit(String arg0) {
aptr.getFilter().filter(arg0.toString());
return true;
}
Set default list to adapter if search not match or search value is blank :
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString().toLowerCase();
FilterResults result = new FilterResults();
if (constraint != null && constraint.toString().length() > 0) {
List<String> founded = new ArrayList<String>();
for (int i = 0, l = orig.size(); i < l; i++) {
if (orig.get(i).toString().toLowerCase().startsWith(constraint.toString().toLowerCase()))
founded.add(orig.get(i));
}
if(founded.size()>0){
result.values = founded;
result.count = founded.size();
}else{
result.values = orig;
result.count = orig.size();
}
} else {
result.values = orig;
result.count = orig.size();
}
return result;
}
来源:https://stackoverflow.com/questions/26786179/searchview-filtering-and-set-suggestions