android custom Switch widget for SwitchPreferenc

2019-04-11 01:23发布

问题:

I search around stackoverflow and find next related topics:

  1. How can i style an Android Switch?
  2. Custom switch widget in Android 4
  3. Set switchStyle - get error resource not found - why?

I also find bugreport on google group: Issue 36636: Unable to override style switchStyle And at last find new probles with Switch widget:

  • I tried to make my own Preference.SwitchPreference and define layout with Switch widget

    android:id="@+android:id/switchWidget"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:thumb="@drawable/switch_thumb"
    android:layout_gravity="center"
    android:padding="16dip"
    android:focusable="false" />
    

but I get an compliation error: Error: Resource is not public. (at 'id' with value '@+android:id/switchWidget'). So I can't use this way.

  • Second way I tried to extend Switch class add set resources from code. But I find that method setThumbResource is availible only from API 16. But I still can't apply @+android:id/switchWidget because it's not public.

So, How can I get custom Switch Preference for SDK API 15 ??? Or how can I customize Switch in Preferences?

回答1:

Just found an awful way to achieve this.

First, src/com/myapp/views/preference/MySwitchPreference.java

public class MySwitchPreference extends SwitchPreference {
    public MySwitchPreference(Context context) {
        super(context);
    }

    public MySwitchPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MySwitchPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onBindView(View view) {
        super.onBindView(view);

        if (view instanceof ViewGroup) {
            setLayout((ViewGroup) view);
        }
    }

    @SuppressLint("NewApi")
    private void setLayout(ViewGroup viewGroup) {
        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;

                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
                    switchView.setThumbResource(com.myapp.R.drawable.switch_inner);
                    switchView.setTrackResource(com.myapp.R.drawable.switch_track);
                }
                return;
            }
            else if (childView instanceof ViewGroup)
                setLayout((ViewGroup) childView);
        }
    }
}

And now, res/xml/preferences.xml

<com.myapp.views.preference.MySwitchPreference
            android:switchTextOff="Off"
            android:switchTextOn="On"
            android:title="whatever"
            android:key="switch" />

A little bit tricky, and only working with Android > 16.



回答2:

Don't know much about the switch issues but you could use a ToggleButton as follows:

Define the button in your layout:

<ToggleButton
            android:id="@+id/your_awesome_toggle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:gravity="center_vertical|center_horizontal"
            android:layout_marginRight="15dp"
            android:textOn=""
            android:textOff=""
            android:background="@drawable/toggle_button"
        />

Create a selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item 
        android:state_checked="false" 
        android:state_focused="false"
        android:drawable="@drawable/switch_off_btn" />
    <item 
        android:state_checked="true" 
        android:state_focused="false" 
        android:drawable="@drawable/switch_on_btn" />
    <item 
        android:drawable="@drawable/switch_off_btn" />
</selector>

OnClickListener:

    toggleOnOff = (ToggleButton) findViewById(R.id.your_awesome_toggle);

    toggleOnOff.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            updateButtons();
            if(toggleOnOff.isChecked()){
                 SharedPreferences emailPrefs = getSharedPreferences(rememberToggleOnOff,MODE_PRIVATE);
                 SharedPreferences.Editor editor = yourPrefs.edit();
                 editor.putBoolean("mon", true);
                 editor.commit();
            }
            else {
                SharedPreferences emailPrefs = getSharedPreferences(rememberToggleOnOff,MODE_PRIVATE);
                SharedPreferences.Editor editor = yourPrefs.edit();
                editor.putBoolean("mon", false);
                editor.commit();
            }
        }
    });
    checkToggleState();

checkToggleState method:

/**
     * Checks the state of the Toggle button preferences.  
     * If preferences are true set the toggle to on, if false set the toggle off.  
     * 
     */
    private void checkToggleState() {
        SharedPreferences yourPrefs = getSharedPreferences(rememberToggleOnOff,MODE_PRIVATE);
        boolean mON = yourPrefs.getBoolean("mon", true);
        if(mON) {
            toggleOnOff.setChecked(true);
        }
        else {
            toggleOnOff.setChecked(false);
        }
    }


回答3:

Change:

android:id="@+android:id/switchWidget"

To:

android:id="@+id/switchWidget"

A simple switch example can be found here.

Switch widget supports 14 and above API level only, but if you want to use Switch Preference pre API level 14, check this.

UPDATE: If you want to style your own switch, try this



回答4:

Inherit SwitchPreference class and use it in preferences.xml with layout pointing to your custom layout. Then in the onBind method of inherited SwitchPreference class you can find corresponding view by id and set listeners. Don't forget to call super in onBind().



回答5:

Change:

android:id="@+android:id/switchWidget"

To:

android:id="@*android:id/switchWidget"