7

Я хочу искать через RecyclerView, у меня есть List<BaseOfCards> (BaseOfCards мой добытчик & класс сеттер) Мой RecyclerViewAdapter:Поиск по RecyclerView с помощью SearchView

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> { 


private LayoutInflater inflater; 
private List<BaseOfCards> items; 

//private int itemLayout; 
//String cardvalue; 
private Activity mActivity; 

public RecyclerViewAdapter(Activity mActivity, Context context, List<BaseOfCards> items) { 
    this.mActivity = mActivity; 
    inflater = LayoutInflater.from(context); 
    this.items = items; 
    //this.itemLayout = itemLayout; 
} 

@Override 
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 

    View view = inflater.inflate(R.layout.custom_row, parent, false); 
    MyViewHolder holder = new MyViewHolder(view, mActivity); 
    return holder; 
} 

@Override 
public void onBindViewHolder(MyViewHolder holder, int position) { 

    BaseOfCards item = items.get(position); 
    holder.title.setTag(item); 
    holder.title.setText(item.getCardName()); 
} 

@Override 
public int getItemCount() { 

    return items.size(); 
} 

public static class MyViewHolder extends RecyclerView.ViewHolder { 
    private Activity mActivity; 
    TextView title; 
    ImageView titileImageView; 

    public MyViewHolder(View itemView, Activity mActivity) { 

     super(itemView); 

     titileImageView = (ImageView) itemView.findViewById(R.id.image_country); 


     title = (TextView) itemView.findViewById(R.id.listText); 
     this.mActivity = mActivity; 

    } 
} 

} 

добавить SearchView в мое меню и инициализировать его в MainActivity:

MenuItem menuItem = menu.findItem(R.id.action_search1); 
    searchView = (SearchView) MenuItemCompat.getActionView(menuItem); 
    SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); 
    searchView.setIconifiedByDefault(true); 

Что мне нужно делать дальше? Сделайте мой RecyclerViewAdapterimplement Filterable или что? Или просто введите класс filter в * RecyclerViewAdapter ** и просто позвоните ему из моего MainActivity?

ответ

19

я решил мою проблему

  1. Сделать мой класс RecyclerViewAdapterimplements Filterable

  2. Добавить линия private List<BaseOfCards> orig;

  3. Добавить метод getFilter в RecyclerViewAdapter

    public Filter getFilter() { 
    return new Filter() { 
        @Override 
        protected FilterResults performFiltering(CharSequence constraint) { 
         final FilterResults oReturn = new FilterResults(); 
         final List<BaseOfCards> results = new ArrayList<BaseOfCards>(); 
         if (orig == null) 
          orig = items; 
          if (constraint != null){ 
           if(orig !=null & orig.size()>0){ 
            for (final BaseOfCards g :orig) { 
             if (g.getCardName().toLowerCase().contains(constraint.toString()))results.add(g); 
            } 
           } 
           oReturn.values = results; 
          } 
          return oReturn; 
         } 
    
    @Override 
        protected void publishResults(CharSequence constraint, FilterResults results) { 
         items = (ArrayList<BaseOfCards>)results.values; 
         notifyDataSetChanged(); 
    
        } 
    }; 
    
  4. Сделать MainActivityimplements SearchView.OnQueryTextListener и изменить метод onQueryTextChange:

    @Override 
    public boolean onQueryTextChange(String newText) { 
        if (TextUtils.isEmpty (newText)) { 
         adapter.getFilter().filter(""); 
        } else { 
         adapter.getFilter().filter(newText.toString()); 
        } 
        return true; 
    } 
    
+0

Прохладный, я добавлю эту функциональность с помощью этого метода ('getFilter') в свой https://github.com/davideas/FlexibleAdapter ;-) – Davidea

+0

@Davidea oh, отлично, спасибо! – Ololoking

+0

Я добавил эту функциональность, но это было сложнее, чем предполагалось. В самом деле, я не уверен, что этот фильтр включен в адаптере *, потому что * Объекты в адаптере ** уже являются ** копией чего-то оригинального, исходящего из источника, такого как DB/XML/JSON, в качестве объекта домена - Проблема заключается не в фильтре, а в добавлении/del/mod, который вы выполняете в ** отфильтрованном списке **: все изменения должны также отражаться в «исходном» списке адаптеров ** И ** в исходном источнике ... В этот момент более удобен для того, чтобы иметь отфильтрованный список копий непосредственно из источника и обновить адаптер с этим списком. – Davidea

0

Использование AutoCompleteTextView или EditText я обрабатываются этот как следующие, где

public List<SalesProductsItems> mItems   

является начальным ListItem экземпляр и.

public static List<SalesProductsItems> filteredIt 

это экземпляр используется для отображения items.Since 1-ый раз, когда фильтр результатов не равно нулю экземпляр mItems будет равен экземпляру filteredIt (таким образом, теряя первоначальный список), а затем по методу publishResults непосредственно перед mItems теряет исходные значения, я приравниваю его к пройденному экземпляру originallist. Надеюсь, что это помогает кто-то

private static class ProductsFilter extends Filter { 

    private final SalesProductsAdapter adapter; 

    private final List<SalesProductsItems> originalList; 

    private final List<SalesProductsItems> filteredList; 

    private ProductsFilter(SalesProductsAdapter adapter, List<SalesProductsItems> originalList) { 
     super(); 
     this.adapter = adapter; 
     this.originalList = new LinkedList<>(originalList); 
     this.filteredList = new ArrayList<>(); 
    } 

    @Override 
    protected FilterResults performFiltering(CharSequence constraint) { 
     filteredList.clear(); 
     final FilterResults results = new FilterResults(); 

     if (constraint == null || constraint.length() == 0) 
      filteredList.addAll(originalList); 
     else { 
      final String filterPattern = constraint.toString().toLowerCase().trim(); 

      for (final SalesProductsItems it : originalList) { 

       if (it.getProduct().toLowerCase().contains(filterPattern)) { 
        filteredList.add(it); 
       } 
      } 
     } 

     results.values = filteredList; 
     results.count = filteredList.size(); 
     return results; 
    } 

    @Override 
    protected void publishResults(CharSequence constraint, FilterResults results) { 
     adapter.mItems = originalList; 
     if(results.count > 0) { 
      filteredIt.clear(); 
      filteredIt.addAll((ArrayList<SalesProductsItems>) results.values); 
      adapter.notifyDataSetChanged(); 
     } else { 
      filteredIt.clear(); 
      filteredIt.addAll(adapter.mItems); 
      adapter.notifyDataSetChanged(); 
     } 
    } 
} 
0

Я хочу добавить к ololoking ответ. В MainActivity мы должны добавить следующий код, чтобы он будет работать:

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.menu_layout, menu); 

    MenuItem searchItem = menu.findItem(R.id.action_search); 
    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); 
    SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); 
    searchView.setIconifiedByDefault(true); 
    searchView.setOnQueryTextListener(this); 
    return super.onCreateOptionsMenu(menu); 

} 

Спасибо ololoking за ваш ответ. Это помогло мне.

0

С того времени другой положительный ответ было сделано, я в настоящее время осуществляется быстро асинхронной фильтр с помощью AsyncTask а в моей FlexibleAdapter библиотеке, производительность очень хорошо с большими списками, имея анимацию тоже! Адаптер настраивается для включения/выключения свойств в результате фильтрации, чтобы увеличить скорость, когда это необходимо. Еще одно большое преимущество заключается в том, что интерфейс по-прежнему реагирует на пользователя.

Тест, выполненный в моем Samsung S3 с Android 6: со стартовым списком из 10.450 элементов, с момента запуска фонового процесса требуется ~ 1 с для фильтрации символа и выбора 3,890 элементов.

Я также сделал Wiki page со всеми подробностями, чтобы использовать фильтр с адаптером.

+0

Я имея такую ​​же проблему, вы решили эту проблему. Пожалуйста, помогите мне @Davidea –

+0

@SagarHudge, с момента моего предыдущего комментария к принятому ответу, мой фильтр изменился, текущий способ фильтрации описан на странице wiki. Пространство, чтобы сделать это лучше и аналогично с классом Filter, есть, но теперь это путь с FlexibleAdapter. – Davidea