Android SwitchPreferences меняются вместе в PreferenceActivity

Я использую SwitchPreference в своем приложении для Android и нашел что-то такое странное. В предпочтении есть более одного SwitchPreference.

Когда я использую стандартную компоновку PreferenceActivity, все работает так хорошо. Но после того, как я установил пользовательский макет для активности предпочтений, эти переключатели начинают сменяться вместе при нажатии любой из них. Я тестирую его на планшете с ручным управлением. Также я тестирую его на своем Android-телефоне, он работает так же.

Как это происходит!

Вот мой собственный макет ( setting.xml ) для предпочтения:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <Button android:id="@+id/button1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button" /> <Button android:id="@+id/button2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button" /> </LinearLayout> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout> 

И PreferenceScreen

 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <SwitchPreference android:key="switch1" android:summary="This is switch 1" android:title="Switch 1" /> <SwitchPreference android:key="switch2" android:summary="This is switch 2" android:title="Switch 2" /> </PreferenceScreen> 

В коде я просто установил пользовательский макет

 public class SettingsActivity extends PreferenceActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.setting); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); setupSimplePreferencesScreen(); } private void setupSimplePreferencesScreen() { addPreferencesFromResource(R.xml.pref_general); } } 

Вот скриншот предпочтения, и два переключателя всегда меняются в одно и то же время, когда вы нажимаете каждый из них. Снимок экрана с предпочтением

Кажется, что onPindView onBindView будет использовать другое представление Switch в качестве параметров.

Вот ошибка в проекте Android в Google Code. Это НЕ эта проблема, но похоже, что оба представления переключателей будут действовать в соответствии с состояниями других коммутаторов.

Поэтому я нашел два пути решения проблемы:

  1. Используйте CheckBoxPreference если на вашем экране больше одного логического предпочтения.
  2. Используйте это обходное решение

     public class CustomSwitchPreference extends SwitchPreference { /** * Construct a new SwitchPreference with the given style options. * * @param context The Context that will style this preference * @param attrs Style attributes that differ from the default * @param defStyle Theme attribute defining the default style options */ public CustomSwitchPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * Construct a new SwitchPreference with the given style options. * * @param context The Context that will style this preference * @param attrs Style attributes that differ from the default */ public CustomSwitchPreference(Context context, AttributeSet attrs) { super(context, attrs); } /** * Construct a new SwitchPreference with default style options. * * @param context The Context that will style this preference */ public CustomSwitchPreference(Context context) { super(context, null); } @Override protected void onBindView(View view) { // Clean listener before invoke SwitchPreference.onBindView ViewGroup viewGroup= (ViewGroup)view; clearListenerInViewGroup(viewGroup); super.onBindView(view); } /** * Clear listener in Switch for specify ViewGroup. * * @param viewGroup The ViewGroup that will need to clear the listener. */ private void clearListenerInViewGroup(ViewGroup viewGroup) { if (null == viewGroup) { return; } int count = viewGroup.getChildCount(); for(int n = 0; n < count; ++n) { View childView = viewGroup.getChildAt(n); if(childView instanceof Switch) { final Switch switchView = (Switch) childView; switchView.setOnCheckedChangeListener(null); return; } else if (childView instanceof ViewGroup){ ViewGroup childGroup = (ViewGroup)childView; clearListenerInViewGroup(childGroup); } } } } 

Я тестировал оба этих решения. Они работают.