2017-06-09 7 views
0

ich versuche Suchfilter in meine RecyclerView zu implementieren, so wie in this postRecyclerView Filter nicht Filterung

ich es ausgetestet habe und es tut die Elemente filtern wie erwartet, aber die Liste scheint nicht in sich ändern die Anwendung. I.E .: ich filter für einen namen und es gibt 7 ergebnisse, und auf dem bildschirm ist es die ursprüngliche liste.

auf Aktivität Meine onCreateMenuOptions ist:

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

    final MenuItem searchItem = menu.findItem(R.id.action_search); 
    final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); 
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { 
     @Override public boolean onQueryTextSubmit(String filterString) { 
      adapter.getFilter().filter(filterString); 
      return true; 
     } 

     @Override 
     public boolean onQueryTextChange(String newText) { 
      return false; 
     } 
    }); 

    return true; 
} 

mein Adapter wie folgt aussieht:

public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHolder> implements INameableAdapter { 
    private List<Anime> items; 
    private List<Anime> filteredItems; 
    private AnimeFilter animeFilter; 

    final private Context context; 

    @Override 
    public Character getCharacterForElement(int element) { 
     Character c = items.get(element).getTitle().charAt(0); 
     if(Character.isDigit(c)){ 
      c = '#'; 
     } 
     return c; 
    } 

    public static class AnimeViewHolder extends RecyclerView.ViewHolder { 
     // Campos respectivos de un item 
     final public ImageView img; 
     final public TextView title; 

     public AnimeViewHolder(View v) { 
      super(v); 
      img = (ImageView) v.findViewById(R.id.image); 
      title = (TextView) v.findViewById(R.id.title); 
     } 
    } 

    public AnimeAdapter(List<Anime> items, Context context) { 
     this.items = items; 
     this.context = context; 
     this.filteredItems = new ArrayList<>(); 
    } 

    @Override 
    public int getItemCount() { 
     return items.size(); 
    } 

    @Override 
    public AnimeViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 

     View v = LayoutInflater.from(viewGroup.getContext()) 
       .inflate(R.layout.anime_card, viewGroup, false); 
     return new AnimeViewHolder(v); 
    } 

    @Override 
    public void onBindViewHolder(AnimeViewHolder viewHolder, int i) { 
     if (BuildConfig.DEBUG) { 
      //This is made to check if the image cache is working as expected. 
      Picasso.with(context).setIndicatorsEnabled(true); 
      Picasso.with(context).setLoggingEnabled(true); 
     } 
     final int position = i; 
     final ImageView imageView = viewHolder.img; 
     Picasso.with(context) 
       .load(items.get(i).getImageUrl()) 
       .into(imageView); 
     viewHolder.title.setText(items.get(i).getTitle()); 

     viewHolder.itemView.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(final View v) { 
       Intent intent = new Intent(context, TabActivity.class); 
       Bundle b = new Bundle(); 
       b.putString("title", items.get(position).title); 
       b.putString("playlist", items.get(position).playlist); 
       imageView.buildDrawingCache(); 
       Bitmap image = imageView.getDrawingCache(); 
       b.putParcelable("imageBitmap", image); 
       intent.putExtras(b); 

       v.getContext().startActivity(intent); 
      } 
     }); 
    } 

    public Filter getFilter() { 
     if(animeFilter == null) 
      animeFilter = new AnimeFilter(this, items); 
     return animeFilter; 
    } 

    private static class AnimeFilter extends Filter { 

     private final AnimeAdapter adapter; 

     private final List<Anime> originalList; 

     private final List<Anime> filteredList; 

     private AnimeFilter(AnimeAdapter adapter, List<Anime> 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.length() == 0) { 
       filteredList.addAll(originalList); 
      } else { 
       final String filterPattern = constraint.toString().toLowerCase().trim(); 

       for (final Anime anime : originalList) { 
        if (anime.getTitle().toLowerCase().contains(filterPattern)) { 
         filteredList.add(anime); 
        } 
       } 
      } 
      results.values = filteredList; 
      results.count = filteredList.size(); 
      return results; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      adapter.filteredItems.clear(); 
      adapter.filteredItems.addAll((ArrayList<Anime>) results.values); 
      adapter.notifyDataSetChanged(); 
     } 
    } 
} 

Was ich hier vergessen?

Vielen Dank im Voraus!

+1

Können Sie alle Codes Ihres Adapters eingeben? –

+0

@ramineftekhari getan, bearbeitet – emboole

Antwort

2

Ich mache einige Änderungen an Ihrem Code.

prüfen dies:

public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHolder> implements INameableAdapter { 
private List<Anime> items; 
private List<Anime> filteredItems; 
private AnimeFilter animeFilter; 

final private Context context; 

@Override 
public Character getCharacterForElement(int element) { 
    Character c = items.get(element).getTitle().charAt(0); 
    if(Character.isDigit(c)){ 
     c = '#'; 
    } 
    return c; 
} 

public static class AnimeViewHolder extends RecyclerView.ViewHolder { 
    // Campos respectivos de un item 
    final public ImageView img; 
    final public TextView title; 

    public AnimeViewHolder(View v) { 
     super(v); 
     img = (ImageView) v.findViewById(R.id.image); 
     title = (TextView) v.findViewById(R.id.title); 
    } 
} 

public AnimeAdapter(List<Anime> items, Context context) { 
    this.items = items; 
    this.context = context; 
    this.filteredItems = new ArrayList<>(); 
    // we copy the original list to the filter list and use it for setting row values 
    this.filteredItems.addAll(items); 
} 

@Override 
public int getItemCount() { 
    return filteredItems.size();//you must always return count of filtered rows 
} 

@Override 
public AnimeViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 

    View v = LayoutInflater.from(viewGroup.getContext()) 
      .inflate(R.layout.anime_card, viewGroup, false); 
    return new AnimeViewHolder(v); 
} 

@Override 
public void onBindViewHolder(AnimeViewHolder viewHolder, int i) { 
    if (BuildConfig.DEBUG) { 
     //This is made to check if the image cache is working as expected. 
     Picasso.with(context).setIndicatorsEnabled(true); 
     Picasso.with(context).setLoggingEnabled(true); 
    } 
    final int position = i; 
    final ImageView imageView = viewHolder.img; 
    Picasso.with(context) 
      .load(filteredItems.get(i).getImageUrl())//we you filteredItems instead of items 
      .into(imageView); 
    viewHolder.title.setText(filteredItems.get(i).getTitle()); 

    viewHolder.itemView.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(final View v) { 
      Intent intent = new Intent(context, TabActivity.class); 
      Bundle b = new Bundle(); 
      b.putString("title", filteredItems.get(position).title); 
      b.putString("playlist", filteredItems.get(position).playlist); 
      imageView.buildDrawingCache(); 
      Bitmap image = imageView.getDrawingCache(); 
      b.putParcelable("imageBitmap", image); 
      intent.putExtras(b); 

      v.getContext().startActivity(intent); 
     } 
    }); 
} 

public Filter getFilter() { 
    if(animeFilter == null) 
     animeFilter = new AnimeFilter(this, items); 
    return animeFilter; 
} 

private static class AnimeFilter extends Filter { 

    private final AnimeAdapter adapter; 

    private final List<Anime> originalList; 

    private final List<Anime> filteredList; 

    private AnimeFilter(AnimeAdapter adapter, List<Anime> 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.length() == 0) { 
      filteredList.addAll(originalList); 
     } else { 
      final String filterPattern = constraint.toString().toLowerCase().trim(); 

      for (final Anime anime : originalList) { 
       if (anime.getTitle().toLowerCase().contains(filterPattern)) { 
        filteredList.add(anime); 
       } 
      } 
     } 
     results.values = filteredList; 
     results.count = filteredList.size(); 
     return results; 
    } 

    @Override 
    protected void publishResults(CharSequence constraint, FilterResults results) { 
     adapter.filteredItems.clear(); 
     adapter.filteredItems.addAll((ArrayList<Anime>) results.values); 
     adapter.notifyDataSetChanged(); 
    } 
} 

}

+0

ich kopiere deinen Code und: - Wenn geladen, Bildschirm ist schwarz. - Wenn Filter, Ergebnisse zeigt. - Wenn ich den Filter lösche, zeigt er am Anfang was er sollte. Ich denke, es ist etwas mit der Ladung von Artikeln auf meiner Aktivität verbunden. Es ergreift eine XML-Liste aus dem Internet, bevor ich meinen Adapter einstelle (neuer AnimeAdapter (items, this);) – emboole

+0

ich änderte den Konstruktor zu diesem: public AnimeAdapter (Liste Items, Kontextkontext) { this.items = items; this.context = Kontext; //this.filteredItems = new ArrayList <>(); this.filteredItems = Elemente; // Wir kopieren die ursprüngliche Liste in die Filterliste und verwenden sie zum Setzen von Zeilenwerten //this.filteredItems.addAll (items); } und es hat gut funktioniert. Danke Mann, ich hatte nicht erwartet, dass dies bis heute funktioniert. Du bist der beste! – emboole

0

Das Problem ist, dass Sie Ihre RecyclerView mit den Einzelteilen aus der items Liste statt filteredItems füllen. In Ihrem Filter aktualisieren Sie nur die filteredItems Liste und benachrichtigen Sie den Adapter, dass sich etwas geändert hat. Tatsächlich bleibt die Liste, die der Adapter verwendet, um die RecyclerView zu füllen, gleich.

Ändern Sie also Ihren Adapter, um immer die gefilterte Liste zu verwenden.

Verwandte Themen