I'm trying to change the icon for my SwitchPreference
depending on its state. If the SwitchPreference
is on, I want the icon set to be @drawable/ic_notifications_active
, but if it's off I want the icon set to be @drawable/ic_notifications_off
.
This is what I have in my PreferenceScreen
xml file:
<SwitchPreference
android:icon="@drawable/ic_notifications_active"
android:key="notifications_switch_preference"
android:defaultValue="true"
app:title="Receive Notifications" />
And this is what it looks like in my design tab:
In my SettingsActivity
, I have this set of code to detect changes to the SwitchPreference
:
notificationsPreference?.onPreferenceChangeListener =
Preference.OnPreferenceChangeListener { preference, newValue ->
val switched: Boolean = (preference as SwitchPreference)
.isChecked
if (switched) {
if (notificationsPreference != null) {
notificationsPreference.icon = resources.getDrawable(R.drawable.ic_notifications_active)
}
} else {
if (notificationsPreference != null) {
notificationsPreference.icon = resources.getDrawable(R.drawable.ic_notifications_off)
}
}
true
}
The problem now is when I run my app and click on the SwitchPreference
toggle for the first time, it changes the icon's color to white, but not the actual icon. When I click again, it then changes icons but it is still white and no longer it's default grey. The wrong icons are now showing for the wrong states.
This is what it looks like for both on and off states:
How do I make it so that when the user clicks on the toggle, it changes to the correct icon and does not change color. I also want it to work on the first try, not on the second.
The wrong icon is displayed because of the next line:
val switched: Boolean = (preference as SwitchPreference).isChecked
preference
object that you get in a callback has old value while newValue
stores the actual new value. You have to use newValue
object to verify whether the switch was enabled or disabled.
Here is an example of a full fragment that switches the icon as expected:
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
val switchPreference: SwitchPreferenceCompat = findPreference("sync")!!
switchPreference.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference, newValue ->
val isChecked = newValue as? Boolean ?: false
if (isChecked) {
switchPreference.icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_baseline_sync_24)
} else {
switchPreference.icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_baseline_sync_disabled_24)
}
true
}
}
}