Skip to content

The Filter Dialog Fragment

Use the filter dialog fragment to filter a collection of data. It can be displayed full screen as an activity on smaller displays or as a dialog on larger displays.

Sample filter dialog

Using the Filter Dialog Fragment

FilterDialogFragment is an abstract class. You must extend it and override a number of methods.

Methods To Override

  • protected abstract void resetChangeHandler(): Resets the values of controls used in the filter.
  • protected abstract void fillCellAtPosition(int section, int row, FormCell view): Assigns values to the form cell for the given section and row.
  • protected abstract int getNumberOfSections(): Returns the number of sections in the view.
  • protected abstract int getCountOfItemsInSection(int section): Returns the number of rows in a given section.
  • protected abstract FormCell.WidgetType getCellTypeInSectionAtRow(int section, int row): Returns the widget type for the control at a given row in the section.
  • protected abstract boolean filterHasChanged(): Indicates if filter values have changed.

Listening For Filter Actions

The filter dialog fragment has three listeners that correspond to the three buttons in the dialog:

  • X to dismiss the dialog
  • APPLY to apply changes
  • RESET ALL to reset the filters contents

OnApplyListener Listener - Applying Changes

This callback is called when a user taps the Apply button in the upper right hand corner of filter dialog fragment.

filterDialogFragment.setApplyListener(new FilterDialogFragmentTest.OnApplyListener() {
    @Override
    public void onApply() {
        // Apply the changed values to your data set.
        JSONObject filterValues = filterDialogFragment.getChangedValues();
        applyFilter(filterValues);
    }
});

OnDismissListener Listener - Dismissing Changes

This callback is called when a user taps the dismiss (X) button in the upper left hand corner of filter dialog fragment.

filterDialogFragment.setDismissListener(new FilterDialogFragmentTest.OnDismissListener() {
    @Override
    public void onDismiss() {
        finish();
    }
});

Reset Filter Contents

When a user taps the RESET ALL button, resetChangeHandler() gets called. You must override this abstract method to reset the values and state of the form cells used in the filter.

Dialog or Activity

We recommend that you code the filter dialog fragment as a dialog, implementing the abstract methods in a new class. In a second class, you can include the dialog as a member to display the filter as an activity.

Coding The Dialog

public class FilterDialogFragmentDemo extends FilterDialogFragment {
    JSONObject changedValues = new JSONObject();
    private boolean mFilterChanged;

    public FilterDialogFragmentDemo() {
        super();
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Assign initial values here ...

        return super.onCreateView(inflater, container, savedInstanceState);
    }

    public JSONObject getChangedValues() {
        return changedValues;
    }

    @Override
    protected void resetChangeHandler() {

        changedValues = new JSONObject();
        mFilterChanged = false;

        // Reassign initial values here ...
.gridSortValueOptions));
    }

    @Override
    protected void fillCellAtPosition(int section, int row, FormCell view) {
        // Assign values to FormCells here ...
    }

    @Override
    protected int getNumberOfSections() {
        return 4;
    }

    @Override
    protected int getCountOfItemsInSection(int section) {
        switch (section) {
            case 0:
                return 1;
            case 1:
                return 2;
            case 2:
                return 1;
            case 3:
                return 1;
            default:
                return 1;
        }
    }

    @Override
    protected FormCell.WidgetType getCellTypeInSectionAtRow(int section, int row) {
        FormCell.WidgetType cellType = null;
        switch (section) {
            case 0:
                switch (row) {
                    case 0:
                        cellType = FormCell.WidgetType.FILTER;
                        break;
                    default:
                        break;
                }
                break;
            case 1:
                switch (row) {
                    case 0:
                        cellType = FormCell.WidgetType.SLIDER;
                        break;
                    case 1:
                        cellType = FormCell.WidgetType.SWITCH;
                        break;
                    default:
                        break;
                }
                break;
            case 2:
                switch (row) {
                    case 0:
                        cellType = FormCell.WidgetType.BUTTON;
                        break;
                    default:
                        break;
                }
                break;
            case 3:
                switch (row) {
                    case 0:
                        cellType = FormCell.WidgetType.SIMPLE_CELL;
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
        return cellType;
    }

    @Override
    public void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        state.putSerializable("FilterData", mFilter);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState != null && savedInstanceState.get("FilterData") != null) {
            mFilter = (FilterDataClass) savedInstanceState.get("FilterData");
        }
    }

    @Override
    protected  boolean filterHasChanged() {
        return mFilterChanged;
    }
}

Coding The Activity

public class FilterActivityDemo extends AbstractActivity {

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

        FilterDialogFragmentDemo filterDialogFragment = (FilterDialogFragmentDemo)
                getSupportFragmentManager().findFragmentById(R.id.fragmentFilter);

        filterDialogFragment.setApplyListener(new FilterDialogFragmentTest.OnApplyListener() {
            @Override
            public void onApply() {
                JSONObject filterValues = filterDialogFragment.getChangedValues();

                Intent result = new Intent("CHANGED_CELLS");
                result.putExtra("CHANGED_CELLS",filterValues.toString());

                setResult(Activity.RESULT_OK, result);
                finish();
            }
        });
        filterDialogFragment.setDismissListener(new FilterDialogFragment.OnDismissListener() {
            @Override
            public void onDismiss() {
                setResult(Activity.RESULT_CANCELED);
                finish();
            }
        });
    }

    @Override
    public void onBackPressed(){
        super.onBackPressed();
        finish();
    }
}

Calling The Dialog And Activity

From the activity where you are displaying the data you want to filter, add code to display the filter and apply the results to your data:

@Override
public void showFilter() {
    if (mUseDialog) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FilterDialogFragmentTest filterDialogFragment = new FilterDialogFragmentTest();
        filterDialogFragment.setApplyListener(new FilterDialogFragmentTest.OnApplyListener() {
            @Override
            public void onApply() {
                JSONObject filterValues = filterDialogFragment.getChangedValues();
                applyFilter(filterValues);
            }
        });
        filterDialogFragment.show(fragmentManager, "dialog");
    } else {
        Intent filterintent = new Intent(this, FilterActivityTest.class);
        startActivityForResult(filterintent,1);
    }
}

void applyFilter(JSONObject filterValues) {
    String sport = filterValues.optString("sport", "");
    if (sport != null && sport.length() > 0) {
        // User has selected a sport.
        runOnUiThread(new Runnable() {
            public void run() {
                List<Country> countryList = createCountryList();
                List<Country> filteredCountryList = new ArrayList<>();
                // Build a list of countries that play the selected sport.
                for (Country country : countryList) {
                    if (country.sport.endsWith(sport)) {
                        filteredCountryList.add(country);
                    }
                }
                countryAdapter = new CountryAdapter(filteredCountryList);
                countryAdapter.notifyDataSetChanged();
                recyclerView.setAdapter(countryAdapter);
            }
        });
    } else {
        runOnUiThread(new Runnable() {
            public void run() {
                List<Country> countryList = createCountryList();
                countryAdapter = new CountryAdapter(countryList);
                countryAdapter.notifyDataSetChanged();
                recyclerView.setAdapter(countryAdapter);
            }
        });
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        try {
            String dataString = data.getStringExtra("CHANGED_CELLS");
            if (dataString != null && dataString.length() > 0) {
                JSONObject filterValues = new JSONObject(data.getStringExtra("CHANGED_CELLS"));
                applyFilter(filterValues);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

Last update: April 14, 2021