Фильтрация SearchView и набор предложений
Я очень новичок в использовании SearchView
, Мне нужен функционал, где у меня есть ActionBar
за что у меня есть Search
, Когда я нажимаю на Поиск, предложения должны отображаться в списке под полем поиска.
Что я сделал до сих пор: добавил поиск в menu.xml и написал код в onCreateOptionsMenu()
где я инициализирую SearchView и setSuggestionsAdapter
также реализовать setOnQueryTextListener
,
Результат: я захожу в приложение, нажимаю на иконку поиска, там отображаются предложения. Я набираю письмо, оно сортирует совпадающие. Я набираю 2-е письмо, оно не показывает никаких предложений Также я закрываю окно поиска и открываю его снова, клавиатура открыта, но предложения в списке не отображаются.
Что мне нужно: Фильтр по введенным пользователем символам. Даже если это более одного персонажа. Всегда показывайте предложения либо по умолчанию со всеми элементами списка, либо предложения, отсортированные по типу пользователя.
Я видел в классе SearchView Android, они устанавливают пустой текст, а также отклоняют предложения. Но я не хочу этого.
Я застрял здесь и не знаю, как поступить. Пожалуйста, помогите мне. Вот мой код адаптера:
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;
}
}
Код в моей деятельности, связанный с меню, где у меня есть вид поиска:
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);
}
}
3 ответа
Мне кажется, что часть проблемы заключается в отсутствии метода getItem().
Если вы посмотрите на исходный код адаптера курсора, getItem() будет получать данные из курсора, а не из вашего отфильтрованного списка, вы хотите, чтобы он получал данные из вашего отфильтрованного списка!
Попробуй это:
@Override
public Object getItem(int position) {
if (position < items.size()) {
return items.get(position);
} else {
return null;
}
}
я забыл добавить, вы также должны изменить это:
private String getSuggestion(int position) {
String suggest1 = (String) searchView.getSuggestionsAdapter().getItem(position);
return suggest1;
}
И чтобы закрыть все, сначала добавьте это в меню createOptions:
@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
...
затем добавьте это в 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;
}
Немного объяснения. Когда вы вызываете setIconified, он либо очистит текст вашего searchView, либо свернет его, в зависимости от состояния по умолчанию. То, что мы там сделали, установили состояние по умолчанию в iconified, поэтому при вызове метода setIconified он очистит текст и свернет представление!
Здравствуйте, я нашел некоторые проблемы с вашим кодом. пожалуйста, попробуйте мой путь. замещать 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();
}
А ТАКЖЕ
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;
}
});
Попробуйте передать значение поиска в фильтр даже пусто:
@Override
public boolean onQueryTextSubmit(String arg0) {
aptr.getFilter().filter(arg0.toString());
return true;
}
Установите список по умолчанию для адаптера, если поиск не соответствует или значение поиска пустое:
@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;
}