Не удается переключить переключатель в Custom SwitchPreference

Я пытаюсь получить пользовательские настройки переключателя в Android. Вот мой код

 switch_widget.xml
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/customswitch"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:focusable="false"
   android:clickable="false" 
   />
  preference xml file :
 <com.tnavitech.utils.CustomSwitch
       android:title="Hide app icon" 
       android:key="hideicon"
       android:defaultValue="false"
       android:disableDependentsState="true"
       android:widgetLayout="@layout/switch_widget" 
    />

Затем я расширяю "SwitchPreference" и в классе "onBindView" и обрабатываю состояния переключателей в OnPreferenceChangeListener:

public class CustomSwitch extends SwitchPreference {

    Switch swit;

    public CustomCheckbox(Context context, AttributeSet attrs) {
    super(context, attrs);

   }

@Override
protected void onBindView(final View rootView) {
    ViewGroup viewGroup= (ViewGroup)rootView;
    super.onBindView(rootView);

    if(swit==null){

        swit  = (Switch) rootView.findViewById(R.id.customswitch);
    }

    this.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference arg0, Object arg1) {

            if (arg1 instanceof Boolean) {
                Boolean enabled = (Boolean) arg1;
                if(enabled){
                    swit.setChecked(true); /// cant toggle switch here
                    Toast.makeText(getContext(), "on", Toast.LENGTH_SHORT).show();


                } else {
                    Toast.makeText(getContext(), "off", Toast.LENGTH_SHORT).show();

                    swit.setSelected(false);     ///cant toggle switch here
            }
            }



            return true;
        }
    });

}

В setOnPreferenceChangeListener я не могу включить или выключить swith. Как я мог решить это? Спасибо!

1 ответ

Дубликат прослушивателя SwitchPreference с настраиваемым макетом.

Идентификатор SwitchView должен быть @android:id/switch_widget вместо того @+id/custom_switch_item или любой другой пользовательский идентификатор.

В источнике SwitchPreference class, мы можем найти код:

View switchView = view.findViewById(AndroidResources.ANDROID_R_SWITCH_WIDGET);

И в AndroidResources:

static final int ANDROID_R_SWITCH_WIDGET = android.R.id.switch_widget;

так что только id = @android:id/switch_widget можно найти правильно.

Вот демонстрация widgetLayout SwitchPreference:

<Switch xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/switch_widget"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical" />

Я работаю над приложением, работающим на устройстве с API 15, поэтому пришлось исправить эту проблему. Решение состоит в том, чтобы иметь две разные компоновки для вашей SwitchPreference вместо одной, которая обрабатывает переключение переключателей. Switch должен быть clickable = false, иначе ваш SwitchPreference не будет обрабатывать никаких кликов.

Во-первых, это раскладка переключателя "в состоянии", где кнопка использует drawable, который представляет кнопку ON:

<?xml version="1.0" encoding="utf-8"?>
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_switch_item"
    android:layout_width="48dp"
    android:layout_height="wrap_content"
    android:textColor="@android:color/white"
    android:textIsSelectable="false"
    android:textSize="0sp"
    android:button="@drawable/ico_toggle_on" //HERE IS DIFFERENCE BETWEEN THESE LAYOUTS
    android:thumb="@android:color/transparent"
    android:track="@android:color/transparent"
    android:clickable="false"
    android:focusable="false"
    android:gravity="center_vertical" />

Второй макет для выключенного состояния:

<?xml version="1.0" encoding="utf-8"?>
<Switch xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_switch_item"
    android:layout_width="48dp"
    android:layout_height="wrap_content"
    android:textColor="@android:color/white"
    android:textIsSelectable="false"
    android:textSize="0sp"
    android:button="@drawable/ico_toggle_off" //HERE IS DIFFERENCE BETWEEN THESE LAYOUTS
    android:thumb="@android:color/transparent"
    android:track="@android:color/transparent"
    android:clickable="false"
    android:focusable="false"
    android:gravity="center_vertical" />

И, наконец, в вашем наборе Activity или Fragment на SwitchPreference OnPreferenceChangeListener, чтобы переключить эти два макета следующим образом:

final SwitchPreference expertSettingsPref = (SwitchPreference) findPreference("expert_settings");
    if (expertSettingsPref != null) {
        expertSettingsPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                preference.setWidgetLayoutResource((Boolean)newValue ? R.layout.custom_switch_preference_on : R.layout.custom_switch_preference_off);
                return true;
            }
        });
    }

Используя SwitchPreferenceCompat с androidX в PreferenceFragmentCompat, по вашему запросу работает следующее.

public class SettingsPageFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.root_preferences, rootKey);

        final SwitchPreferenceCompat switchPreference = (SwitchPreferenceCompat) findPreference("switch");
        if(switchPreference != null){
            switchPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    // get the incoming value
                    boolean isOn = (Boolean) newValue;

                    // get the incoming control
                    SwitchPreferenceCompat switchPreference = (SwitchPreferenceCompat) preference;

                    // set the incoming value to the incoming control
                    switchPreference.setChecked(isOn);

                    // do whatever else you wanted to when this event fires

                }
            });
        }
    }

Я подозреваю, что причина того, что ваш код не работает, заключается в том, что "Swit" может быть вне зоны действия слушателя. В моем примере это передается как предпочтение.

Другие вопросы по тегам