• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Implementing Search Filter in Adapter that parses a JSON

mark9

Lurker
I would like to implement a search filter in my adapter class (used in a fragment class showing a list of colors), but although I managed to do it for simpler examples, I don't know how to proceed in this class that receives a json array; I would like to filter the search on the colorCode, since I am not using pojo classes I don't know how to filter just using strings in getFilter() method. Thank you.

Java:
package ...

import...

public class ColorListAdapter extends RecyclerView.Adapter {

   private JSONArray colorList;

   public ColorListAdapter(JSONArray json){
       super();
       if(json != null){
           this.colorList = json;
       }
   }

   @NonNull @override
   public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
       View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fragment_color_view, viewGroup, false);
       return new ColorListHolder(view);
   }

   @override
   public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
       try {
           ((ColorListHolder)viewHolder).setContentValue(i);
       } catch (JSONException e) {
           e.printStackTrace();
       }
   }

   @override
   public int getItemCount() {
       return this.colorList.length();
   }

   private class ColorListHolder extends RecyclerView.ViewHolder {

       private TextView colorCodeText;
       private TextView colorNameText;
       private CardView imageView;

       public ColorListHolder(@NonNull View itemView) {
           super(itemView);
           this.colorCodeText = itemView.findViewById(R.id.colorCode_text);
           this.colorNameText = itemView.findViewById(R.id.colorName_text);
           this.imageView = itemView.findViewById(R.id.colorView);
       }

       public void setContentValue(int index) throws JSONException {
           this.colorNameText.setText(((JSONObject)colorList.get(index)).getString("Name"));
           this.colorCodeText.setText(((JSONObject)colorList.get(index)).getString("ColorCode"));
           this.imageView.setCardBackgroundColor(Color.parseColor(((JSONObject)colorList.get(index)).getString("HexString")));
       }
   }

}
 
Thank you for answer. I would to filter the list of colors by color name. I have seen examples where getFilter() method is overriden, but in my code I can't do the filtering on a json array and reload list according to that filter..
 
I am trying this, but It does not work properly..

Java:
public class ColorListAdapter extends RecyclerView.Adapter implements Filterable {

    private JSONArray colorList;

    private List<String> colorListFiltered = new ArrayList<String>();

    public ColorListAdapter(JSONArray json) throws JSONException {
        super();
        if (json != null) {
            this.colorList = json;

                for (int i=0;i<json.length();i++){
                    //colorListFiltered.add((colorList.getString(i)));
                    colorListFiltered.add(json.getJSONObject(i).getString("Name"));
                }
        }
    }


    @Override
    public Filter getFilter() {
        return new colorFilter();
    }


    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.fragment_color_view, viewGroup, false);
        return new ColorListHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
        try {
            ((ColorListHolder) viewHolder).setContentValue(i);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

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

    private class ColorListHolder extends RecyclerView.ViewHolder {

        private TextView colorCodeText;
        private TextView colorNameText;
        private CardView imageView;

        public ColorListHolder(@NonNull View itemView) {
            super(itemView);
            this.colorCodeText = itemView.findViewById(R.id.colorCode_text);
            this.colorNameText = itemView.findViewById(R.id.colorName_text);
            this.imageView = itemView.findViewById(R.id.colorView);
        }

        public void setContentValue(int index) throws JSONException {

            this.colorNameText.setText(colorListFiltered.get(index));
            //this.colorNameText.setText(((JSONObject) colorList.get(index)).getString("Name"));
            
                this.colorCodeText.setText(((JSONObject) colorList.get(index)).getString("ColorCode"));
                this.imageView.setCardBackgroundColor(Color.parseColor(((JSONObject) colorList.get(index)).getString("HexString")));

        }
    }


    public class colorFilter extends Filter{

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {

            FilterResults Result = new FilterResults();
            // if constraint is empty return the original names

            if(constraint.length() == 0 ) {
                ArrayList<String> arrColorList = new ArrayList<>();
                for (int i = 0; i < colorList.length(); i++) {
                    try {
                        arrColorList.add(colorList.getJSONObject(i).getString("Name"));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                Result.values = arrColorList;
                Result.count = arrColorList.size();
                return Result;
            }

            /*if(constraint.length() == 0 ){
                Result.values = colorList;
                Result.count = colorList.length();
                return Result;*/

            else {

                List<String> Filtered_Names = new ArrayList<String>();
                String filterString = constraint.toString().toLowerCase();
                String filterableString = "";

                for (int i = 0; i < colorList.length(); i++) {
                    try {
                        filterableString = (colorList.getJSONObject(i)).getString("Name");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    if (filterableString.toLowerCase().contains(filterString)) {
                        Filtered_Names.add(filterableString);
                    }
                }

                Result.values = Filtered_Names;
                Result.count = Filtered_Names.size();
                return Result;

            }

        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {

            colorListFiltered = (ArrayList<String>) results.values;
            notifyDataSetChanged();
        }
    }


}
 
Last edited:
By "doesn't work properly", what exactly do you mean?

It might be helpful to add some logging throughout the code to see exactly how things are interacting and what data is being processed? That would make it easier to show here exactly what is happening.
 
I edited Adapter...now the list doesn't crash, but items are inverted while I perform filtering. I think that setContentValue() need to be fixed, maybe this is caused by different indexes of colorListFiltered and colorList. Or Maybe I should return also other strings (needed by setcontentValue) in Filter method.
 
Last edited:
Back
Top Bottom