Android SwitchPreferences在PreferenceActivity中一起更改

Android SwitchPreferences在PreferenceActivity中一起更改,android,Android,我在Android应用程序中使用SwitchPreference,发现了一些奇怪的东西。首选项中有多个SwitchPreference 当我使用PreferenceActivity的默认布局时,一切都很好。但是,在我将“自定义布局”设置为“首选项”活动之后,当您单击其中任何一个开关时,这些开关将一起开始更改。我正在基于arm的平板电脑上测试它。我还在我的安卓手机上测试了它,它的工作原理是一样的 这是怎么发生的 以下是我的自定义布局(setting.xml),以供选择: <?xml vers

我在Android应用程序中使用SwitchPreference,发现了一些奇怪的东西。首选项中有多个SwitchPreference

当我使用PreferenceActivity的默认布局时,一切都很好。但是,在我将“自定义布局”设置为“首选项”活动之后,当您单击其中任何一个开关时,这些开关将一起开始更改。我正在基于arm的平板电脑上测试它。我还在我的安卓手机上测试了它,它的工作原理是一样的

这是怎么发生的

以下是我的自定义布局(
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>
这是首选项的屏幕截图,每次单击这两个开关时,这两个开关总是同时更改。

似乎SwitchPreference的
onBindView
将使用其他
Switch
视图作为参数

下面是谷歌代码中的Android项目。不是这个问题,但类似,都描述了交换机视图将根据其他交换机的状态进行操作

所以我找到了两种解决问题的方法:

  • 如果屏幕中有多个布尔首选项,请使用
    CheckBoxPreference
  • 使用此解决方法

    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);
                }
            }
        }
    
    }
    
    公共类CustomSwitchPreference扩展了SwitchPreference{
    /**
    *使用给定的样式选项构造新的SwitchPreference。
    *
    *@param context将设置此首选项样式的上下文
    *@param attrs样式属性与默认值不同
    *@param defStyle主题属性定义默认样式选项
    */
    公共CustomSwitchPreference(上下文上下文、属性集属性、int-defStyle){
    超级(上下文、属性、定义样式);
    }
    /**
    *使用给定的样式选项构造新的SwitchPreference。
    *
    *@param context将设置此首选项样式的上下文
    *@param attrs样式属性与默认值不同
    */
    公共CustomSwitchPreference(上下文、属性集属性){
    超级(上下文,attrs);
    }
    /**
    *使用默认样式选项构造新的SwitchPreference。
    *
    *@param context将设置此首选项样式的上下文
    */
    公共CustomSwitchPreference(上下文){
    super(上下文,null);
    }
    @凌驾
    受保护的void onBindView(视图){
    //在调用SwitchPreference.onBindView之前清除侦听器
    ViewGroup ViewGroup=(ViewGroup)视图;
    clearListenerInViewGroup(视图组);
    super.onBindView(视图);
    }
    /**
    *清除指定视图组开关中的侦听器。
    *
    *@param viewGroup需要清除侦听器的视图组。
    */
    私有void clearListenerInViewGroup(视图组视图组){
    如果(null==viewGroup){
    返回;
    }
    int count=viewGroup.getChildCount();
    对于(int n=0;n

  • 我已经测试了这两种解决方案。它们很有效。

    猜同一个actionlistener?你没有加it@DanielBo是的,我还没有添加actionlistener,但是在我为它设置自定义布局之前,它工作得很好。Android是否将相同的默认actionlistener设置为switchpreferences,sames Impossible从未使用过preferenceAcitvity,所以我不知道:),尝试使用其他键进行切换,可能我对switch1 switch2不太满意,因为我认为这些键在共享时用于映射prefs@DanielBo这只是一个演示。我正在开发的真正应用程序中的开关具有完全不同的键。太棒了!谢谢@Garnel。刚刚实现了CustomSwitchPreference,它对我来说非常有用。拯救了我的一天!我只是使用了CheckBoxPreference
    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);
        }
    }
    
    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);
                }
            }
        }
    
    }