Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter rows from Cursor so they don't show up in ListView

Tags:

android

I have a Cursor that returns rows I use with a SimpleCursorAdapter to populate a ListView. I would like to filter some of the rows so they don't get displayed in my ListView. I use the data from the rows elsewhere in my Activity so I don't want to change my SQL to filter them with a WHERE clause.

What is the best way to keep a row from being displaying in my ListView? Ideally I would check a column in my row and then only add rows to the ListView that satisfy a condition.

like image 790
Richard Avatar asked Jun 12 '10 04:06

Richard


3 Answers

Create a CursorWrapper and override the move...() methods to convert positions in the filtered set (which is what the ListView will see) and positions in the actual Cursor. Then, use your CursorWrapper in the SimpleCursorAdapter.

like image 120
CommonsWare Avatar answered Nov 17 '22 00:11

CommonsWare


Thanks, this helps me a lot! Use it if you need:

private class FilterCursorWrapper extends CursorWrapper {     
    private String filter;
    private int column;
    private int[] index;
    private int count=0;
    private int pos=0;

    public FilterCursorWrapper(Cursor cursor,String filter,int column) {
        super(cursor);
        this.filter = filter.toLowerCase();
        this.column = column;
        if (this.filter != "") {
            this.count = super.getCount();
            this.index = new int[this.count];
            for (int i=0;i<this.count;i++) {
                super.moveToPosition(i);
                if (this.getString(this.column).toLowerCase().contains(this.filter))
                    this.index[this.pos++] = i;
            }
            this.count = this.pos;
            this.pos = 0;
            super.moveToFirst();
        } else {
            this.count = super.getCount();
            this.index = new int[this.count];
            for (int i=0;i<this.count;i++) {
                this.index[i] = i;
            }
        }
    }

    @Override
    public boolean move(int offset) {
        return this.moveToPosition(this.pos+offset);
    }

    @Override
    public boolean moveToNext() {
        return this.moveToPosition(this.pos+1);
    }

    @Override
    public boolean moveToPrevious() {
        return this.moveToPosition(this.pos-1);
    }

    @Override
    public boolean moveToFirst() {
        return this.moveToPosition(0);
    }

    @Override
    public boolean moveToLast() {
        return this.moveToPosition(this.count-1);
    }

    @Override
    public boolean moveToPosition(int position) {
        if (position >= this.count || position < 0)
            return false;
        this.pos = position;
        return super.moveToPosition(this.index[position]);
    }

    @Override
    public int getCount() {
        return this.count;
    }

    @Override
    public int getPosition() {
        return this.pos;
    }

}

https://gist.github.com/ramzes642/5400792

like image 39
Roman Usachev Avatar answered Nov 17 '22 00:11

Roman Usachev


In Romans's solution add

this.pos = position;

in method

@Override
public boolean moveToPosition(int position) {
    if (position >= this.count || position < 0)
        return false;
    return super.moveToPosition(this.index[position]);
}

Otherwise you will get some problems when using .moveToNext() and .moveToPrevious().

like image 34
Jeyhey Avatar answered Nov 17 '22 01:11

Jeyhey