Jijkz
Jijkz

Reputation: 15

listview gives wrong item on click after filtering

I have a listView with a custom adapter which implements filterable. The filter function works finally perfectly fine, up until I try to open an item within the listView. When I try to open my filtered result, it moves me to the wrong activity. I've gone through some different approaches from other posts, one of which (latest attempt) is marked as a comment in my code down below.

What's weird to me is why this problem occurs, since I'm using a simple "if-else" case...

Another post, which I can't find anymore, suggested to use set/get-tag, which I'm not very familiar with. I also suspect the issue might lie within the filter, since the filter doesnt give out the arrayList, but the filtered version of it. However, I couldn't figure that one out, either.

Any help is appreciated!

MainActivity down to its core:

public class MainActivity extends AppCompatActivity implements TextWatcher{
    MyAdapter adapter;`

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView lw = findViewById(R.id.lw);
        Button notiz = findViewById(R.id.btnNotiz);
        Button merk = findViewById(R.id.btnMerk);
        EditText suche = findViewById(R.id.suchen);

        lw.setLongClickable(true);

        final ArrayList<Objekt> arrayList = new ArrayList();

        arrayList.add(new Objekt("AAA", "AAA-Street"));
        arrayList.add(new Objekt( "BBB","BBB-Street")); // and so on

        adapter = new MyAdapter(this,arrayList);
        suche.addTextChangedListener(this);

        Collections.sort(arrayList, new Comparator<Objekt>() {
            @Override
            public int compare(Objekt o1, Objekt o2) {
              return o1.getKuerzel().compareToIgnoreCase(o2.getKuerzel());
            }
        });

        lw.setAdapter(adapter);

        lw.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                TextView textView = view.findViewById(R.id.textViewFullAdress);
                ClipboardManager cm = (ClipboardManager)
                        getSystemService(Context.CLIPBOARD_SERVICE);
                assert cm != null;
                cm.setText(textView.getText().toString());

                Toast.makeText(MainActivity.this, "Kopiert!", Toast.LENGTH_SHORT).show();
                return false;
            }
        });

        lw.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String selection = arrayList.get(position).getKuerzel();
                //one of the things I've tried: Objekt selection = (Objekt)((MyAdapter)parent.getAdapter()).getItem(position);
                if(selection.equals("AAA")){
                    Intent intent0 = new Intent(MainActivity.this, AAA.class);
                    startActivity(intent0);
                } else if(selection.equals("BBB")){
                    Intent intent0 = new Intent(MainActivity.this, BBB.class);
                    startActivity(intent0);
                } //and so on
           }
        });

    }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            adapter.getFilter().filter(s);
        }

        @Override
        public void afterTextChanged(Editable s) {

        }

MyAdapter:

public class MyAdapter extends BaseAdapter implements Filterable {

    Context context;
    ArrayList<Objekt> arr, tempArr;
    CustomFilter cs;

    public MyAdapter(Context context, ArrayList<Objekt> arr) {
        this.context = context;
        this.arr = arr;
        this.tempArr = arr;
    }

    @Override
    public int getCount() {
        return arr.size();
    }

    @Override
    public Object getItem(int position) {
        return arr.get(position);
        //return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        convertView = LayoutInflater.from(context).inflate(R.layout.adapter_view_layout,parent,false);

        TextView kuerzel = convertView.findViewById(R.id.textViewKuerzel);
        TextView fullAdress = convertView.findViewById(R.id.textViewFullAdress);

        kuerzel.setText(arr.get(position).getKuerzel());
        fullAdress.setText(arr.get(position).getFullAdress());

        return convertView;
    }

    @Override
    public Filter getFilter() {
        if (cs == null){
            cs = new CustomFilter();
        }

    return cs;
    }

    class CustomFilter extends Filter{
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            if (constraint != null && constraint.length()>0) {
                constraint = constraint.toString().toUpperCase();

                ArrayList<Objekt> filters = new ArrayList<Objekt>();

                for (int i = 0; i < tempArr.size(); i++) {
                    if (tempArr.get(i).getKuerzel().toUpperCase().contains(constraint)) {
                        Objekt objekt = new Objekt(tempArr.get(i).getKuerzel(), tempArr.get(i).getFullAdress());
                        filters.add(objekt);
                    }
                }
                results.count = filters.size();
                results.values = filters;
            }
            else
            {
                results.count = tempArr.size();
                results.values = tempArr;
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            arr = (ArrayList<Objekt>)results.values;
            notifyDataSetChanged();
        }
    }

Objekt:

public class Objekt {

    String kuerzel;
    String fullAdress;

    public Objekt(String kuerzel, String fullAdress) {
        this.kuerzel = kuerzel;
        this.fullAdress = fullAdress;
    }

    public String getKuerzel() {
        return kuerzel;
    }

    public void setKuerzel(String kuerzel) {
        this.kuerzel = kuerzel;
    }

    public String getFullAdress() {
        return fullAdress;
    }

    public void setFullAdress(String fullAdress) {
        this.fullAdress = fullAdress;
    }
}

I haven't quite figured out formatting here, sorry...

Upvotes: 0

Views: 395

Answers (1)

Ravi Kumar
Ravi Kumar

Reputation: 4508

After applying the filter in MyAdapter class, the elements in the arr in MyAdapter and arrayList in the MainActivity will be different. for example, if initially your list contains ['AAA','BBB','AAC','CCC','DDD'] then both the list will have same elements:

arrayList = ['AAA','BBB','AAC','CCC','DDD'] // in MainActivity
arr = ['AAA','BBB','AAC','CCC','DDD'] // in MyAdapter

Now if you apply the filter by typing 'AA', the elements of the arr will be updated but arraylist will remain same.

arrayList = ['AAA','BBB','AAC','CCC','DDD'] // in MainActivity
arr = ['AAA','AAC'] // in MyAdapter

Now if the user has selected the second element from the list i.e. at index 1. In your MainActivity, you have used String selection = arrayList.get(position).getKuerzel();

It will return 'BBB' as you are selecting index 1 from the arrayList.

The solution to the problem is to filter arrayList as well in onTextChanged method.

 @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        adapter.getFilter().filter(s);
        //filter arrayList
    }

Upvotes: 1

Related Questions