Adding List Preference Settings using Preference Fragment Compat

In this blog post we will see how we can add a Preference List in Settings which will display a list of radio buttons in UI which user can choose from. In Open Event Orga App, the Organizer had a choice to switch between viewing Net Sales or Gross Sales in the App’s Dashboard. We decided to use a preference list to allow the user to select between using Net or Gross Sales.

The benefit of using Preference List and not any other storage media (like SQLite) to store the information is that, Preference List stores the information as key-value pair in SharedPreferences which makes it easy to store and extract small amount of data with strong consistency guarantees and using less time. Let’s move on to the implementation.

Implementation

Firstly add the dependency in build.gradle.

implementation “com.takisoft.fix:preference-v7:27.1.0.0”

In the preferences layout file, we will use checkboxes.

<PreferenceScreen xmlns:android=”http://schemas.android.com/apk/res/android”>

<CheckBoxPreference
android:key=”@string/gross_sales_key”
android:title=”@string/gross_sales”
android:defaultValue=”true” />

<CheckBoxPreference
android:key=”@string/net_sales_key”
android:title=”@string/net_sales”
android:defaultValue=”false” />
</PreferenceScreen>

We will create SalesDataSettings class which extends PreferenceFragmentCompat and override onCreatePreferenceFix method. We will request PreferenceManager and set SharedPreferencesName. The manager will be used to store and retrieve key-value pairs from SharedPreferences. Using setPreferencesFromResource we will attach the layout file to the fragment.

PreferenceManager manager = getPreferenceManager();
manager.setSharedPreferencesName(Constants.FOSS_PREFS);

setPreferencesFromResource(R.xml.sales_data_display, rootKey);

We are using CheckBox Preferences and modifying their behaviour to work as a Radio Preference List because Radio reference is not provided by Android. We are initializing two checkboxes and attaching a preference listener to unset all other checkboxes which one is selected.

CheckBoxPreference netSales = (CheckBoxPreference) findPreference(NET_SALES);
CheckBoxPreference grossSales = (CheckBoxPreference) findPreference(GROSS_SALES);

Preference.OnPreferenceChangeListener listener = (preference, newValue) -> {
String key = preference.getKey();

switch (key) {
case GROSS_SALES:
netSales.setChecked(false);
break;
case NET_SALES:
grossSales.setChecked(false);
break;
default:
break;
}
return (Boolean) newValue;
};

netSales.setOnPreferenceChangeListener(listener);
grossSales.setOnPreferenceChangeListener(listener);

We can load SalesDataDisplay Fragment class when a preference button is clicked using fragment transactions as shown below.

findPreference(getString(R.string.sales_data_display_key)).setOnPreferenceClickListener(preference -> {
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, SalesDataSettings.newInstance())
.addToBackStack(null)
.commit();
return true;
});

References

  1. Shared Preferences Documentation https://developer.android.com/reference/android/content/SharedPreferences
  2. Gericop Takisoft Android-Support-Preference-V7-Fix https://github.com/Gericop/Android-Support-Preference-V7-Fix
  3. Codebase for Open Event Organizer App https://github.com/fossasia/open-event-orga-app