以编程方式更改 Switch 的颜色

programmatically change color of Switch

我正在尝试创建一个简单的自定义开关小部件,用于侦听 SharedPreferences 中某个键值的变化。下面是我的代码:

public class CustomSwitch extends SwitchCompat implements SharedPreferences.OnSharedPreferenceChangeListener {

    private static final String TAG = CustomSwitch.class.getSimpleName();

    private boolean isSwitchTintColorPrimary;

    public CustomSwitch(Context context) {
        this(context, null);
    }

    public CustomSwitch(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initializeView(context, attrs);
    }

    private void initializeView(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomSwitch, 0, 0);
        try {
            isSwitchTintColorPrimary = ta.getBoolean(R.styleable.CustomSwitch_tintColorPrimary, false);
        } finally {
            ta.recycle();
        }
        applyTheme();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        registerThemeChangeListener();
    }

    private void registerThemeChangeListener() {
        if (getContext() != null)
            ColoriyoPreference.getSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        unRegisterThemeChangeListener();
    }

    private void unRegisterThemeChangeListener() {
        if (getContext() != null)
            ColoriyoPreference.getSharedPreferences(getContext()).unregisterOnSharedPreferenceChangeListener(this);
    }

    private void applyTheme() {
        ColorStateList thumbStates = new ColorStateList(
                new int[][]{
                        {android.R.attr.state_checked, android.R.attr.state_enabled},
                        {-android.R.attr.state_checked, android.R.attr.state_enabled},
                        {}
                },
                new int[]{
                        isSwitchTintColorPrimary ? ColoriyoPreference.getColor(getContext()) : ContextCompat.getColor(getContext(), R.color.colorPrimary),
                        ContextCompat.getColor(getContext(), R.color.grey_50),
                        ContextCompat.getColor(getContext(), R.color.grey_50)
                }
        );
        setThumbTintList(thumbStates);

        ColorStateList trackStates = new ColorStateList(
                new int[][]{
                        new int[]{-android.R.attr.state_enabled},
                        new int[]{}
                },
                new int[]{
                        Color.GRAY,
                        Color.LTGRAY
                }
        );
        setTrackTintList(trackStates);
        setTrackTintMode(PorterDuff.Mode.OVERLAY);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals(PREFERENCE_KEY_COLOR)) {
            applyTheme();
        }
    }
}

在布局中:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.chintansoni.android.themedemo.MainActivity"
    tools:showIn="@layout/activity_main">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.chintansoni.android.themedemo.customview.themeview.CustomTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView textColor"
            app:textColorPrimary="true" />

        <com.chintansoni.android.themedemo.customview.themeview.CustomButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button Background"
            app:backgroundColorPrimary="true" />

        <com.chintansoni.android.themedemo.customview.themeview.CustomSwitch
            android:id="@+id/switch_main"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textOff="Off"
            android:textOn="On"
            app:tintColorPrimary="true" />
    </LinearLayout>

    <uz.shift.colorpicker.LineColorPicker
        android:id="@+id/picker"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_margin="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:orientation="horizontal" />

</android.support.constraint.ConstraintLayout>

但我的视图未在 UI 中呈现。另外,我想知道这段代码是否会优先监听颜色变化并在运行时反映颜色变化?

有什么建议吗?

我唯一缺少的东西:

public CustomSwitch(Context context, AttributeSet attrs) {
    this(context, attrs, R.attr.switchStyle); // <--- passing default Style Attribute 
}

我改进后的class如下:

public class CustomSwitch extends SwitchCompat implements SharedPreferences.OnSharedPreferenceChangeListener {

    private boolean isSwitchTintColorPrimary;

    public CustomSwitch(Context context) {
        this(context, null);
    }

    public CustomSwitch(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.switchStyle);
    }

    public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initializeView(context, attrs);
    }

    private void initializeView(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomSwitch, 0, 0);
        try {
            isSwitchTintColorPrimary = ta.getBoolean(R.styleable.CustomSwitch_tintColorPrimary, false);
        } finally {
            ta.recycle();
        }
        applyTheme();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        registerThemeChangeListener();
    }

    private void registerThemeChangeListener() {
        if (getContext() != null)
            ColoriyoPreference.getSharedPreferences(getContext()).registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        unRegisterThemeChangeListener();
    }

    private void unRegisterThemeChangeListener() {
        if (getContext() != null)
            ColoriyoPreference.getSharedPreferences(getContext()).unregisterOnSharedPreferenceChangeListener(this);
    }

    private void applyTheme() {
        ColorStateList thumbStates = new ColorStateList(
                new int[][]{
                        {android.R.attr.state_checked, android.R.attr.state_enabled},
                        {-android.R.attr.state_checked, android.R.attr.state_enabled},
                        {}
                },
                new int[]{
                        isSwitchTintColorPrimary ? ColoriyoPreference.getColor(getContext()) : ContextCompat.getColor(getContext(), R.color.colorPrimary),
                        ContextCompat.getColor(getContext(), R.color.grey_50),
                        ContextCompat.getColor(getContext(), R.color.grey_50)
                }
        );
        setThumbTintList(thumbStates);

        ColorStateList trackStates = new ColorStateList(
                new int[][]{
                        new int[]{android.R.attr.state_enabled},
                        new int[]{-android.R.attr.state_enabled}
                },
                new int[]{
                        Color.LTGRAY,
                        Color.GRAY,
                        Color.LTGRAY
                }
        );
        setTrackTintList(trackStates);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals(ColoriyoPreference.PREFERENCE_KEY_COLOR)) {
            applyTheme();
        }
    }
}