Фильтрация 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;

}
Другие вопросы по тегам