Search code examples
androidandroid-preferencesswitchpreference

Enable/disable two more SwitchPreference when one switch Preference is enabled


When one preference is selected, other two preferences should be available for clicks, otherwise the should be shady/dim so that the user knows they are not clickable. Like how we set alpha for text. Attached the code below. Please Let me know if there is a solution.

<PreferenceCategory
        android:title="@string/category_dnd_title"
        app:iconSpaceReserved="false">

        <androidx.preference.SwitchPreferenceCompat
            android:defaultValue="false"
            android:key="key1"
            android:title="title1" />

        <androidx.preference.SwitchPreferenceCompat
            android:defaultValue="false"
            android:dependency="key1"
            android:key="key2"
            android:title="title2" />

        <androidx.preference.SwitchPreferenceCompat
            android:defaultValue="false"
            android:dependency="key1"
            android:key="@key3"
            android:title="title3"/>
    </PreferenceCategory>

Solution

  • To do this, you need some fragment class to manage your preferences in code.

    public class PreferenceFragment extends PreferenceFragmentCompat {
    
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.your_xml, rootKey);
            
            final SharedPreferences preferences = androidx.preference.PreferenceManager.getDefaultSharedPreferences(getActivity());
    
            // dont forget to check nullity in real app production, findPreference could return null
            final SwitchPreferenceCompat switchPreference1 = (SwitchPreferenceCompat) findPreference("key1");
            final SwitchPreferenceCompat switchPreference2 = (SwitchPreferenceCompat) findPreference("key2");
            final SwitchPreferenceCompat switchPreference3 = (SwitchPreferenceCompat) findPreference("key3");
            if (preferences.getBoolean("key1", false)) {
                switchPreference2.setEnabled(true);
                switchPreference3.setEnabled(true);
            } else {
                switchPreference2.setEnabled(false);
                switchPreference3.setEnabled(false);
            }
            switchPreference1.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    boolean turned = (Boolean) newValue;
                    if (turned) {
                        switchPreference2.setEnabled(true);
                        switchPreference3.setEnabled(true);
                    } else {
                        switchPreference2.setEnabled(false);
                        switchPreference3.setEnabled(false);
                    }
                    preferences.edit().putBoolean("key1", turned).apply();
                    return true;
                }
            });
    
        }
    }
    

    @EDIT
    You can override an SwitchPreferenceCompat class to make an enabled/disabled effect

    public class CustomSwitchPreference extends SwitchPreferenceCompat {
    
        public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyle, int defStyleRes) {
            super(context, attrs, defStyle, defStyleRes);
        }
    
        public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public CustomSwitchPreference(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CustomSwitchPreference(Context context) {
            super(context, null);
        }
    
        @Override
        public void onBindViewHolder(PreferenceViewHolder holder) {
            super.onBindViewHolder(holder);
            TextView title = (TextView) holder.findViewById(android.R.id.title);
            TextView summary = (TextView) holder.findViewById(android.R.id.summary);
            if (title.isEnabled()) {
                title.setTextColor(Color.BLACK);
            } else {
                title.setTextColor(Color.GRAY);
            }
    
            if (summary.isEnabled()) {
                summary.setTextColor(Color.BLACK);
            } else {
                summary.setTextColor(Color.GRAY);
            }
        }
    }
    

    In that case your preference xml should look like this

    <PreferenceCategory
        android:title="Category"
        app:iconSpaceReserved="false"
        >
    
        <com.test.CustomSwitchPreference
            android:defaultValue="false"
            android:key="key1"
            android:title="title1"
            />
    
        <com.test.CustomSwitchPreference
            android:defaultValue="false"
            android:key="key2"
            android:title="title2"
            />
    
        <com.test.CustomSwitchPreference
            android:defaultValue="false"
            android:key="key3"
            android:title="title3"
            />
    
    </PreferenceCategory>
    

    And you should change an access to the preference in fragment like

        final CustomSwitchPreference switchPreference1 = (CustomSwitchPreference) findPreference("key1");
        final CustomSwitchPreference switchPreference2 = (CustomSwitchPreference) findPreference("key2");
        final CustomSwitchPreference switchPreference3 = (CustomSwitchPreference) findPreference("key3");