Bypassing the bug in filtering that does not update ListView Android
Asked Answered
A

3

5

Here is the code, I used a custom adapter, and applied the Filter method, now the ListView does not update when the backspace key is entered, on when one switches back from an item activity. I read it is a bug in filter, but how do I bypass it, I know of apps that have achieved this kind of setup I want.

public class IndexPageActivity extends Activity implements OnItemClickListener{ 
    ListView listView;
    EditText editTextB;
    PagesAdapter adapter1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.pageList);
        editTextB = (EditText) findViewById(R.id.searchB);
        adapter1 = new PagesAdapter(this);
        listView.setAdapter(adapter1);
        adapter1.notifyDataSetChanged();
        listView.setOnItemClickListener(this);

        editTextB.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
                IndexPageActivity.this.adapter1.getFilter().filter(cs.toString());
                adapter1.notifyDataSetChanged();
            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1,
                        int arg2, int arg3) { }

            @Override
            public void afterTextChanged(Editable arg0) { }
        });
    }

    @Override
    public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3) {
        Intent i;
        String name = adapter1.getItem(position);
        Log.d("id", name);

        if (name.equals("Item1"))
        {
            i = new Intent(this, anActivity.class);
            startActivity(i);
        }
        else if (name.equals("Item2"))
        {
            i = new Intent(this, anActivity2.class);
            startActivity(i);
        }
    }
}

class SingleRow {
    String pagedata;
    SingleRow(String pagedata){
        this.pagedata=pagedata;
    }
}
class PagesAdapter extends BaseAdapter implements Filterable{
    ArrayList<String> pagelist;
    List<String> arrayList;
    Context context;
    String [] pagedatas;

    PagesAdapter(Context c){
        context=c;
        pagelist = new ArrayList<String>();
        Resources res = c.getResources();
        pagedatas = res.getStringArray(R.array.pages_data);
        for (int i=0;i<463;i++){
            pagelist.add(pagedatas[i]);
        }
    }
    @Override
    public int getCount() {
        return pagelist.size();
    }

    @Override
    public String getItem(int i) {
        return pagelist.get(i);
    }

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

    @Override
    public View getView(int i, View view, ViewGroup viewG) {
        LayoutInflater inflater=(LayoutInflater)             context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View row=inflater.inflate(R.layout.single_row,viewG,false);
        TextView pagetitle = (TextView) row.findViewById(R.id.textViewRow);

        String temp=pagelist.get(i);

        pagetitle.setText(temp);
        return row;
    }

    public class filter_here extends Filter{
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults Result = new FilterResults();
            // if constraint is empty return the original names
            if(constraint.length() == 0 ){
                Result.values = pagelist;
                Result.count = pagelist.size();
                return Result;
            }

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

            for(int i = 0; i<pagelist.size(); i++){
                filterableString = pagelist.get(i);
                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) {
            pagelist = (ArrayList<String>) results.values;
            notifyDataSetChanged();
        }
    }

    @Override
    public Filter getFilter() {
        return new filter_here();
    }
}
Arndt answered 22/11, 2013 at 14:4 Comment(0)
E
3

Finally found the bug of the backspace, you had some error in the filter function, that am returning an ArrayList, instead of the List that holds the variable the code should the final code is:

public class IndexPageActivity extends Activity implements OnItemClickListener{ 
ListView listView;
EditText editTextB;
PagesAdapter adapter1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.pageList);
        editTextB = (EditText) findViewById(R.id.searchB);
        adapter1 = new PagesAdapter(this);
        listView.setAdapter(adapter1);
        adapter1.notifyDataSetChanged();
        listView.setOnItemClickListener(this);

        editTextB.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence cs, int arg1, int arg2,
                    int arg3) {
                // When user changed the Text
                IndexPageActivity.this.adapter1.getFilter().filter(cs.toString());
                adapter1.notifyDataSetChanged();
            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1,
                    int arg2, int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub
            }
        });
}


@Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3) {
// TODO Auto-generated method stub
Intent i;
String name = adapter1.getItem(position);
        Log.d("id", name);
if (name.equals("Item1"))
{
    i = new Intent(this, anActivity.class);
    startActivity(i);
}
else if (name.equals("Item2"))
{
    i = new Intent(this, anActivity2.class);
    startActivity(i);
}
}
}


class SingleRow {
String pagedata;
SingleRow(String pagedata){
    this.pagedata=pagedata;
}
}
class PagesAdapter extends BaseAdapter implements Filterable{
ArrayList<String> pagelist;
List<String> arrayList;
Context context;
String [] pagedatas;

PagesAdapter(Context c){
context=c;
pagelist = new ArrayList<String>();
Resources res = c.getResources();
pagedatas = res.getStringArray(R.array.pages_data);

for (int i=0;i<463;i++){
    pagelist.add(pagedatas[i]);
}
arrayList = pagelist;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return arrayList.size();
}

@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}

@Override
public String getItem(int i) {
// TODO Auto-generated method stub
return arrayList.get(i);
}

@Override
public long getItemId(int i) {
// TODO Auto-generated method stub
return i;
}


@Override
public View getView(int i, View view, ViewGroup viewG) {
// TODO Auto-generated method stub
LayoutInflater inflater=(LayoutInflater)                 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row=inflater.inflate(R.layout.single_row,viewG,false);
TextView pagetitle = (TextView) row.findViewById(R.id.textViewRow);

String temp=arrayList.get(i);

pagetitle.setText(temp);
return row;
}

@Override
public Filter getFilter() {
// TODO Auto-generated method stub
Filter filter = new Filter() {
    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {

        arrayList = (List<String>) results.values;
        notifyDataSetChanged();
    }

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

     FilterResults results = new FilterResults();
        ArrayList<String> FilteredArrayNames = new ArrayList<String>();

        if (pagelist == null)    {
            pagelist = new ArrayList<String>(arrayList);
        }
        if (constraint == null || constraint.length() == 0) {
            results.count = pagelist.size();
            results.values = pagelist;
        } else {
            constraint = constraint.toString().toLowerCase();
            for (int i = 0; i < pagelist.size(); i++) {
                String dataNames = pagelist.get(i);
                if (dataNames.toLowerCase().startsWith(constraint.toString()))  {
                    FilteredArrayNames.add(dataNames);
                }
            }

            results.count = FilteredArrayNames.size();
            System.out.println(results.count);

            results.values = FilteredArrayNames;
            Log.e("VALUES", results.values.toString());
        }

        return results;
}
};
return filter;
}
}
Easley answered 22/11, 2013 at 19:20 Comment(6)
Thank you, I'm going to input this and get back to you ASAP! Thanks a lot.. All Credits to You Coderji!Nicobarese
Yeah Coderji! It does work, another thing came up tho, when I input say Twinkle in the editText, it brings the items related, when I use the backspace to delete them all, the List displayed will be of items starting with the first letter "T" in Twinkle. The same if Chocolate was input in the editText, when backspaced, only items that start with "C" are displayed in the ListView. Good work though Boss!Nicobarese
strange?! did you change anything beside the onItemClick? in my side of the application. it works like a charmEasley
It works, it works, must be the emulator I used. It does work! Yay! Thank you Coderji!Nicobarese
my pleasure helping you man learnt alot from it :) hope i deserve a rating ;)Easley
Could yhu help me check this? - #20242818Nicobarese
C
4

1) Backspace Filtering

In your publishResults, you are modifying your pagelist, so if you press backspace and filter again, pagelist only contains a small portion of the original pagelist entries:

So, you need to keep a copy of your original data! Something like:

List<String> allData;

PagesAdapter(Context c) {
    ...
    allData = pagelist;
    ...
}

and in your filter method, use the allData object:

for (int i = 0; i < allData.size(); i++) {
    filterableString = allData.get(i);
    if (filterableString.toLowerCase().contains(filterString)) {
        Filtered_Names.add(filterableString);
    }
}

and also where you reset your data back to the original:

// if constraint is empty return the original names
if (constraint.length() == 0) {
    Result.values = allData;
    Result.count = allData.size();
    return Result;
}

2) Clear filter after returning from another activity:

This can be done in onResume... Personally, i would clear the text in the editText as to reset the filter like so:

@Override
protected void onResume() {
    if (editTextB != null) {
        editTextB.setText("");
    }
    super.onResume();
}
Commercial answered 22/11, 2013 at 14:31 Comment(0)
E
3

Finally found the bug of the backspace, you had some error in the filter function, that am returning an ArrayList, instead of the List that holds the variable the code should the final code is:

public class IndexPageActivity extends Activity implements OnItemClickListener{ 
ListView listView;
EditText editTextB;
PagesAdapter adapter1;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.pageList);
        editTextB = (EditText) findViewById(R.id.searchB);
        adapter1 = new PagesAdapter(this);
        listView.setAdapter(adapter1);
        adapter1.notifyDataSetChanged();
        listView.setOnItemClickListener(this);

        editTextB.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence cs, int arg1, int arg2,
                    int arg3) {
                // When user changed the Text
                IndexPageActivity.this.adapter1.getFilter().filter(cs.toString());
                adapter1.notifyDataSetChanged();
            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1,
                    int arg2, int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub
            }
        });
}


@Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3) {
// TODO Auto-generated method stub
Intent i;
String name = adapter1.getItem(position);
        Log.d("id", name);
if (name.equals("Item1"))
{
    i = new Intent(this, anActivity.class);
    startActivity(i);
}
else if (name.equals("Item2"))
{
    i = new Intent(this, anActivity2.class);
    startActivity(i);
}
}
}


class SingleRow {
String pagedata;
SingleRow(String pagedata){
    this.pagedata=pagedata;
}
}
class PagesAdapter extends BaseAdapter implements Filterable{
ArrayList<String> pagelist;
List<String> arrayList;
Context context;
String [] pagedatas;

PagesAdapter(Context c){
context=c;
pagelist = new ArrayList<String>();
Resources res = c.getResources();
pagedatas = res.getStringArray(R.array.pages_data);

for (int i=0;i<463;i++){
    pagelist.add(pagedatas[i]);
}
arrayList = pagelist;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return arrayList.size();
}

@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}

@Override
public String getItem(int i) {
// TODO Auto-generated method stub
return arrayList.get(i);
}

@Override
public long getItemId(int i) {
// TODO Auto-generated method stub
return i;
}


@Override
public View getView(int i, View view, ViewGroup viewG) {
// TODO Auto-generated method stub
LayoutInflater inflater=(LayoutInflater)                 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row=inflater.inflate(R.layout.single_row,viewG,false);
TextView pagetitle = (TextView) row.findViewById(R.id.textViewRow);

String temp=arrayList.get(i);

pagetitle.setText(temp);
return row;
}

@Override
public Filter getFilter() {
// TODO Auto-generated method stub
Filter filter = new Filter() {
    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {

        arrayList = (List<String>) results.values;
        notifyDataSetChanged();
    }

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

     FilterResults results = new FilterResults();
        ArrayList<String> FilteredArrayNames = new ArrayList<String>();

        if (pagelist == null)    {
            pagelist = new ArrayList<String>(arrayList);
        }
        if (constraint == null || constraint.length() == 0) {
            results.count = pagelist.size();
            results.values = pagelist;
        } else {
            constraint = constraint.toString().toLowerCase();
            for (int i = 0; i < pagelist.size(); i++) {
                String dataNames = pagelist.get(i);
                if (dataNames.toLowerCase().startsWith(constraint.toString()))  {
                    FilteredArrayNames.add(dataNames);
                }
            }

            results.count = FilteredArrayNames.size();
            System.out.println(results.count);

            results.values = FilteredArrayNames;
            Log.e("VALUES", results.values.toString());
        }

        return results;
}
};
return filter;
}
}
Easley answered 22/11, 2013 at 19:20 Comment(6)
Thank you, I'm going to input this and get back to you ASAP! Thanks a lot.. All Credits to You Coderji!Nicobarese
Yeah Coderji! It does work, another thing came up tho, when I input say Twinkle in the editText, it brings the items related, when I use the backspace to delete them all, the List displayed will be of items starting with the first letter "T" in Twinkle. The same if Chocolate was input in the editText, when backspaced, only items that start with "C" are displayed in the ListView. Good work though Boss!Nicobarese
strange?! did you change anything beside the onItemClick? in my side of the application. it works like a charmEasley
It works, it works, must be the emulator I used. It does work! Yay! Thank you Coderji!Nicobarese
my pleasure helping you man learnt alot from it :) hope i deserve a rating ;)Easley
Could yhu help me check this? - #20242818Nicobarese
E
1

How about putting

adapter1.notifyDataSetChanged();

in onResume() method of the Activity?

Encipher answered 22/11, 2013 at 14:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.