SwitchPreference Listener with Custom Layout

后端 未结 3 585
Happy的楠姐
Happy的楠姐 2021-01-14 20:35

I\'m trying to use a SwitchPreference in my Settings page, but i can\'t get the listener to work. I am using a custom widget layout in order to style the switch, as I cannot

相关标签:
3条回答
  • 2021-01-14 21:30

    I ran into the same issue, my solution is similar to the followings:

    1. In your custom switch layout, add following code. This "uncovers" the preference, and makes the whole block clickable. That's why the listener is not triggered at all.

      android:clickable="false" android:focusable="false"

    2. Extend "SwitchPreference", and in "onBindView" class, get states from SharedPreferences, and handle switch states change there.

      public class MySwitchPreference extends SwitchPreference {
      
          public MySwitchPreference(Context context) {
              super(context, null);
          }
      
          public MySwitchPreference(Context context, AttributeSet attrs) {
              super(context, attrs);
          }
          public MySwitchPreference(Context context, AttributeSet attrs, int defStyle) {
              super(context, attrs, defStyle);
          }
      
          protected void onBindView(View view) {
              // Clean listener before invoke SwitchPreference.onBindView
              ViewGroup viewGroup= (ViewGroup)view;
              clearListenerInViewGroup(viewGroup);
              super.onBindView(view);
      
              final Switch mySwitch = (Switch) view.findViewById(R.id.custom_switch_item);
              Boolean initVal = this.getPersistedBoolean(false);
              if (initVal) {
                  mySwitch.setChecked(true);
              }
              this.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
                  @Override
                  public boolean onPreferenceChange(Preference preference, Object newValue) {
                      //Do your things here, toggling the switch and so on
                      return true;
                  }
              });
          }
      
          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);
                  }
              }
          }
      }
      

    Hopefully this can help you. I was not able to find any solution for my case until I figured it out this way.

    0 讨论(0)
  • 2021-01-14 21:30

    The id of SwitchView should be @android:id/switch_widget instead of @+id/custom_switch_item or any other custom id.

    In the source of SwitchPreference class, we can find the code:

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

    and in AndroidResources:

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

    so only id = @android:id/switch_widget can be found correctly.

    Here's a demo about SwitchPreference's widgetLayout:

    <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" />
    
    0 讨论(0)
  • 2021-01-14 21:36

    Solution – based on @RickCase answer, but works with both Switch and SwitchCompat.

    0 讨论(0)
提交回复
热议问题