This tutorial adds a setting to the ShopList app created in the RecyclerViews tutorial, and adapted in the Fragment's tutorial. Whilst the functionality could be included in the version of the app that doesn't use Fragments, this tutorial will reference files in the version that does.
In the app so far, when we add one of any item to the shopping list, it doesn't always make sense when displayed, for example if we add 'cheese' to the shopping list, it displays a '1 cheese'. Some, but not all users might like to hide the count when it is one. In order to facilitate this, we can add a settings screen to our application where the user can determine whether this functionality should be enabled or not
<?xml version="1.0" encoding="utf-8"?>
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
</androidx.preference.PreferenceScreen>
Within this screen we can define various settings as needed by the application, they can even be grouped, however we only need a single application, with a setting which can be turned on and off, so we will use a SwitchPreference to do so<SwitchPreference android:key="hide_single_count"
android:title="@string/hide_count_1"
android:summary="@string/hide_count_1_description"
android:defaultValue="false" />
You can read more about creating preferences in the Android documentation<string name="hide_count_1">Hide count of 1</string>
<string name="hide_count_1_description">When the count of an item is 1, hide the number in the list</string>
Android makes it easy to display settings, we can programmatically create a Fragment which will automatically provide a layout for the settings defined in the preferences XML file. This makes use of a backwards compatibility library, which must add to the project first
implementation 'androidx.preference:preference:1.1.1'
class SettingsFragment : PreferenceFragmentCompat() {
}
onCreatePreferences method
p0
and p1
in the above method, rename them to savedInstanceState
and rootKey
respectivelysetPreferencesFromResource(R.xml.preferences,rootKey)
This is all that is needed to create a Fragment that displays user preferences.As we will want to display the settings fragment in its own Activity, we need to create an activity which just holds the Fragment
onCreate
activity, add the following code:
supportFragmentManager.beginTransaction().replace(android.R.id.content, SettingsFragment()).commit()
This replaced the content of the Activity with that of the SettingsFragment. Other than writing code to load the Activity, this is all that is needed to display settings in an Android appWe now need to provide a way for the user to access the settings. You may recall from the RecyclerView tutorial, that we actually removed a settings menu! Now we will add one back again
<item android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
onOptionsItemSelected(item: MenuItem): Boolean
, which will launch the settings activity when the menu button is pressed:
if (item.itemId == R.id.action_settings){
val intent = Intent(this,SettingsActivity::class.java)
startActivity(intent)
}
Although the settings can be changed, they don't yet affect the running of the application.
onBindViewHolder()
method, after the item
variable is declared, add the following code:
val prefs = PreferenceManager.getDefaultSharedPreferences(holder.itemView.context)
val hideSingleCount = prefs.getBoolean("hide_single_count",false)
if (item.count == 1 && hideSingleCount){
cardView.tvCount.visibility = View.GONE
} else {
cardView.tvCount.visibility = View.VISIBLE
}
Note that the first two lines access the shared preferences and get the Boolean value associated with the "hide_single_count" key (which we declared in the preferences.xml file earlier). The final line switch determine the visibility of the TextView which displays the count. Note that we use View.GONE
and not View.INVISIBLE
so no space is consumed when it is hidden. It's also important to ensure that we don't just use the View.GONE statement, as when recycling a ViewHolder, we may need to change a previously 'Gone' View to be visible againvar prefsChangedListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
notifyDataSetChanged()
}
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
PreferenceManager.getDefaultSharedPreferences(recyclerView.context).registerOnSharedPreferenceChangeListener(prefsChangedListener)
}
You may have noticed that the margins differ on the count TextView and the item name TextView.
A completed version of this task can be found on GitHub