-1

i'm trying to make a custom adapter to fill a ListView with strings and their corresponding images. problem is that when the filtering takes place, images keep the same order as when they were not filtered as opposed to strings that are correctly filtered and displayed. i know i'm missing something here to connect the strings and images together. right now two ArrayLists (with matching indices) keep the strings and their images.

import android.app.Activity;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;


public class WorterAdapter extends ArrayAdapter<String> implements Filterable
{
    private final Activity context;
    private ArrayList<String> words;
    private ArrayList<String> words_original;
    private ArrayList<Integer> images;
    private @LayoutRes int layout;
    private @IdRes int image_view;
    private @IdRes int text_view;
    private WortFilter filter;

    public WorterAdapter(Activity context,@LayoutRes int layout, @IdRes int text_view, @IdRes int image_view, ArrayList<String> words, ArrayList<Integer> images)
    {
        super(context, R.layout.wort_layout, words);
        this.context = context;
        this.words = words;
        this.words_original = new ArrayList<>(words);
        this.images = images;
        this.text_view = text_view;
        this.image_view = image_view;
        this.layout = layout;
    }
    @Override
    public View getView(int position, View view, ViewGroup parent)
    {
        LayoutInflater inflater = context.getLayoutInflater();
        View rowView= inflater.inflate(layout, null, true);
        TextView txtTitle = (TextView) rowView.findViewById(text_view);
        ImageView imageView = (ImageView) rowView.findViewById(image_view);
        txtTitle.setText(words.get(position));
        imageView.setImageResource(images.get(position));
        return rowView;
    }

    public Filter getFilter()
    {
        if (filter == null)
        {
            filter = new WortFilter();
        }
        return filter;
    }
    private class WortFilter extends Filter
    {
        @Override
        protected FilterResults performFiltering(CharSequence constraint)
        {
            FilterResults results = new FilterResults();;
            if(constraint == null || constraint.length() == 0)
            {
                words = new ArrayList<>(words_original);
                results.values = words;
                results.count = words.size();
            }
            else
            {
                words = new ArrayList<>(words_original);
                ArrayList<String> newValues = new ArrayList<>();
                for (String i : words)
                {
                    if (i.toUpperCase().contains(constraint.toString().toUpperCase()))
                        newValues.add(i);
                }
                results.values = newValues;
                results.count = newValues.size();
            }
            // TODO Auto-generated method stub
            return results;
        }
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results)
        {
            if (results.count == 0)
            {
                notifyDataSetInvalidated();
                clear();
            }
            else
            {
                @SuppressWarnings("unchecked")
                ArrayList<String> lst = (ArrayList<String>)results.values;
                words = new ArrayList<>(lst);
                clear();
                for (String item : words)
                {
                    add(item);
                }
                notifyDataSetChanged();
            }
        }
    }
}

i know this question has been asked several times but i can't get the other solutions to work for me.

M47
  • 400
  • 2
  • 13

2 Answers2

1

You are just filtering words and neither words_original nor images, so I'm guessing also your 'original words' are off after filtering.

e.g. after filtering you have 3 elements in words (the filtered items), but the other 2 array lists still contain all the items, leading to the problem you described.

Apply the filter to your whole dataset (words, words_original, and images) and it should work.

David Medenjak
  • 33,993
  • 14
  • 106
  • 134
  • thanks. i didn't know that getView gets called for filtered results as well. i thought i'm missing an @Override... btw `words_original` should be there to refill `words` when the filtering criteria becomes empty again. otherwise all the list data would be lost after the first filter. – M47 Feb 27 '16 at 20:55
0

The problem is that you are only filtering the words list and not the images list also. So as soon as one word is filtered out from the word list the word and image lists are no longer parallel which is causing the wrong image to be shown.

You could fix this by creating an images_original list and also removing elements at the same index of your images list. In other words if you remove a word you also need to remove the corresponding image at the same location.

However, a better approach would be to store both values in a single object and create a list based on the new object. So create a new class that has a String word and int image and keep a single list composed of the new class. This will simplify things for you and then you also only have to filter a single list instead of two separate lists.

George Mulligan
  • 11,813
  • 6
  • 37
  • 50