Skip to content Skip to sidebar Skip to footer

How To Apply Multiple Filters On An Adapter?

I got a listView with and a search field that calls my Adapter's getFilter().filter(keyword) func. It is working very nice, but i would like to add an other filter that searches in

Solution 1:

I suppose that you implemented the filter yourself. As you cant get two filters you could have a field in the filter that defines what kind of filtering should by applied ( you could use multiple filters in your filter).

Set you field of the filter to the value you want before using the filter.

Or:

Use the keyword to choose the filter to apply. Add on the beginning of the keyword some characters which define the filter to apply. With String.beginsWith() you can check which type of filtering has to by applied. This has to be done in the Filter itself. The caller of the getFilter.filter(keyword) has to know what characters have to by added in front of the string.

Solution 2:

Apply Multiple Filter in Listview and also use the multi sorting in ListView, try this link:

https://github.com/apurv3039/filter_listview/tree/master

Solution 3:

I had a similar need and I've written for myself. The filter are combined with AND operator. Keep it as simple as possible. Not claiming it is perfect but it works for me. You can change according to your need.

The ItemModel

publicclassItemModel {

    publicint ID;
    publicint rating;
    publicfloat avg;
    public String name;
    public String shortDesc;
    publicboolean read;
}

And the parser.java

/**
 * This class is designed to be simple for parsing a filter of the form
 *             "object field name: variable type: operator: value"
 *
 * "ID:int:>:20";"name:string:=:20"
 * Where ';' means AND, however this is not parsed here.
 * If you need different logic, use the results.O
 *
 * Multiple filters seperated by ';'
 */publicclassParser {

    privatestaticfinalStringTAG="Parser";


    publicstaticbooleanisPassingTheFiler(String filter, String field, String val) {

        String[] mGroups = parseMainGroups(filter);

        for (String mGroup : mGroups) {

            Log.e(TAG,"Working on the main Group " +mGroup );

            String[] subCommand = parseSubCommand(mGroup);

            if ( field.equals(subCommand[0])) {
                if (!processCommand(subCommand, val)) {
                    returnfalse;
                }
            }
        }

        returntrue;
    }

    /**
     * parses that data assuming they are all sperated by `;`
     */publicstatic String[] parseMainGroups(CharSequence commands) {

        Stringbuffer= commands.toString();

        String parts[] = buffer.split(";");

        return parts;
    }

    publicstatic String[] parseSubCommand(String subCommand) {

        //remove the double quotes.Stringbuffer= removeDoubleQuotes(subCommand.toString());

        String parts[] = buffer.split(":");

        return parts;
    }

    publicstatic String removeDoubleQuotes(String quotedString) {

        if ((quotedString.charAt(0) == '\"') && (quotedString.charAt(quotedString.length() - 1) == '\"')) {
            return quotedString.substring(1, quotedString.length() - 1);
        } else {
            Log.e(TAG, quotedString + " doesn't contained in double quotes!\nReturned empty string!!!");
            return"";
        }
    }

    publicstaticbooleanprocessCommand(String[] subCommand, String val) {

        switch (subCommand[1]) {

            case"int":
                Log.e("TAG","\tint Filer");
                return intStatement(subCommand, val);
            case"float":
                Log.e("TAG","\tfloat Filer");
                return floatStatement(subCommand, val);
            case"string":
                Log.e("TAG","\tString Filer");
                return stringStatement(subCommand, val);

            default:
                returnfalse;
        }
    }

    /**
     * Evaluate the Int statement's correctness with the given INT value
     */publicstaticbooleanintStatement(String[] subCommand, String cVal) {

        StringoperString= subCommand[2];

        int iVal;
        int val;

        try {
            iVal = Integer.parseInt(subCommand[3]);
            val = Integer.parseInt(cVal);
        } catch (NumberFormatException e) {
            returnfalse;
        }

        switch (operString) {

            case"=":
                returnval== iVal;
            case"<":
                return val < iVal;
            case">":
                return val > iVal;
            case"<=":
                return val <= iVal;
            case">=":
                return val >= iVal;
            case"!=":
                return val != iVal;
            case"s" :
                //digit search as string. We look into string from that we already havereturn cVal.contains(subCommand[3]);

            default:
                Log.e("Parser", "invalid Integer Operation");

                returnfalse;
        }
    }


    publicstaticbooleanfloatStatement(String[] subCommand, String cVal) {

        StringoperString= subCommand[2];
        float iVal;
        float val;

        try {
            iVal = Float.parseFloat(subCommand[3]);
            val = Float.parseFloat(cVal);

        } catch (NumberFormatException e) {
            returnfalse;
        }

        switch (operString) {

            case"=":
                returnval== iVal;
            case"<":
                return val < iVal;
            case">":
                return val > iVal;
            case"<=":
                return val <= iVal;
            case">=":
                return val >= iVal;
            case"!=":
                return val != iVal;
            case"s" :
                //digit search as string. We look into string from that we already havereturn cVal.contains(subCommand[3]);

            default:

                Log.e("Parser", "invalid Integer Operation");

                returnfalse;
        }
    }

    publicstaticbooleanstringStatement(String[] subCommand, String val) {

        StringoperString= subCommand[2];

        switch (operString) {

            case"=":
                //equalityreturn val.equals(subCommand[3]);
            case"<":
                //substringreturn val.contains(subCommand[3]);
            case"sw":
                //prefixreturn val.startsWith(subCommand[3]);
            case"ew":
                //postfixreturn val.endsWith(subCommand[3]);

            default:

                Log.e("Parser", "invalid Integer Operation");

                returnfalse;
        }
    }
}

The private filter class in the adapter.

privateclassItemFilterextendsFilter {

        @Overrideprotected FilterResults performFiltering(CharSequence constraint) {
            StringcharString= constraint.toString();
            String[] parts;

            FilterResultsfilterResults=newFilterResults();

            if (charString.isEmpty()) {
                filterResults.values = newArrayList<>(itemList);
            } else {
                //Parse the main group
                parts = parseMainGroups(charString);

                if (parts.length < 1) {
                    filterResults.values =  newArrayList<>(itemList);

                } else {

                    List<ItemModel> filteredList = newArrayList<>();

                    for (ItemModel row : itemList) {

                        if ( !isPassingTheFiler(charString,"ID",""+row.ID)) {
                            continue;
                        } else {
                            Log.e("Filter", "passed on ID" + row.ID);
                        }
                        if ( !isPassingTheFiler(charString,"name",""+row.name)) {
                            continue;
                        } else {
                            Log.e("Filter", "passed on name" + row.name);
                        }
                        // passed every test asked. If empty they returned true!
                        filteredList.add(row);
                    }

                    filterResults.values = newArrayList<>(filteredList);
                }
            }

            return filterResults;
        }

        @OverrideprotectedvoidpublishResults(CharSequence constraint, FilterResults results) {

            updateList((List<ItemModel>) results.values);

        }
    }

And the updateList member funtion for the adapter

publicvoidupdateList(List<ItemModel> newList) {
        DiffUtil.DiffResultdiffResult= DiffUtil.calculateDiff(newItemDiffUtilCallback(newList, itemListFiltered));

        itemListFiltered.clear();
        itemListFiltered.addAll(newList);
        diffResult.dispatchUpdatesTo(this);

        Log.e("TAG", "updated with dispatch");
    }

And the difutils that helps the good animation

publicclassItemDiffUtilCallbackextendsDiffUtil.Callback {

    private List<ItemModel> oldList;
    private List<ItemModel> newList;

    publicItemDiffUtilCallback(List<ItemModel> newList, List<ItemModel> oldList) {
        this.newList = newList;
        this.oldList = oldList;
    }

    @OverridepublicintgetOldListSize() {
        return oldList.size();
    }

    @OverridepublicintgetNewListSize() {
        return newList.size();
    }

    @OverridepublicbooleanareItemsTheSame(int oldItemPosition, int newItemPosition) {
        return oldList.get(oldItemPosition).ID == newList.get(newItemPosition).ID;
    }

    @OverridepublicbooleanareContentsTheSame(int oldItemPosition, int newItemPosition) {

         return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
    }


    @Overridepublic Object getChangePayload(int oldItemPosition, int newItemPosition) {
        returnsuper.getChangePayload(oldItemPosition, newItemPosition);
    }

Post a Comment for "How To Apply Multiple Filters On An Adapter?"