Search code examples
android-5.0-lollipopswitchpreference

Android 5.x SwitchPreference is not behaving the same as in Android 4.x


I have a code using SwitchPreference that used to work with Android 4.x however it no longer works since I updated my device to Android 5.0.1.

I have a simple SwitchPreference which displays a title on the left and an ON/OFF switch on the right.

    <SwitchPreference
        android:key="myPref"            
        android:selectable="true"
        android:title="Title" 
        android:fragment="com.myApp.DeviceMonitorPrefsActivity"            
        android:switchTextOn="ON"
        android:switchTextOff="OFF"/>

On the PreferenceActivity, I overrode onPreferenceTreeClick() to perform an Action (launching a setup Activity in my case) when I click on the title of this SwitchPreference control.

    @Override
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) 
    {
        if(preference instanceof SwitchPreference){
            // My Action
        }
    }

With Android 4.4.4, this Action used to be executed only when I pressed to the left of this control (title), but not when I changed the switch state.

Now with Android 5.0.1, the onPreferenceTreeClick() is called even when I change the switch state, and I didn't find a way to differentiate the two cases.

Is it a bug in Android 5.0.1 or is there a way to make this work cleanly?


Solution

  • This workaround found here seems to work : https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=172425

    Here's my implementation that work on my case :

    public class MySwitchPreference 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 MySwitchPreference(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 MySwitchPreference(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 MySwitchPreference(Context context) {
        super(context, null);
    }
    
    @Override
    protected void onBindView(View view) {
        ViewGroup viewGroup= (ViewGroup)view;
        setSwitchClickable(viewGroup);
        super.onBindView(view);
    }
    
    private void setSwitchClickable(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.setClickable(true);
              return;
          } else if (childView instanceof ViewGroup){
            ViewGroup childGroup = (ViewGroup)childView;
            setSwitchClickable(childGroup);
          }
      }
    
    }
    

    Then you just have to use your own "MySwitchPreference" into SwitchPreference directly.