Reputation: 775
I'm using SwitchPreference in my Android app and found something so weird. There is more than one SwitchPreference in the preference.
When I use the default layout of PreferenceActivity, everything works so well. But after I set custom layout to the preference activity, those Switches begin change together when you click any of them. I'm testing it on a arm-based tablet. Also I test it on my Android phone, It works just so the same.
How does it happens!
Here is my custom layout (setting.xml
) for preference:
<?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>
and the 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>
In the code, I just set the custom layout
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);
}
}
Here is the screenshot of the preference, and the two switch always change at the same time what ever you click each of them.
Upvotes: 5
Views: 4018
Reputation: 775
It seems that SwitchPreference's onBindView
will use other Switch
view as the parameters.
Here is a bug issue in Android project in Google Code. It's NOT this problem, but similar, both describes switch views will act according to other switches' states.
So I found two way to solve the problem:
CheckBoxPreference
if there are more than one boolean preference in your screen.Use this workaround
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);
}
}
}
}
I've tested both of the two solutions. They works.
Upvotes: 7