com.tencent.tws.assistant.widget.CheckBox.java Source code

Java tutorial

Introduction

Here is the source code for com.tencent.tws.assistant.widget.CheckBox.java

Source

/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tencent.tws.assistant.widget;

import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;

import com.tencent.tws.assistant.drawable.TwsAnimatedStateListDrawable;
import com.tencent.tws.assistant.drawable.TwsRippleDrawable;
import com.tencent.tws.assistant.support.v4.widget.TintableCompoundButton;
import com.tencent.tws.assistant.utils.ThemeUtils;
import com.tencent.tws.sharelib.R;

/**
 * A {@link CheckBox} which supports compatible features on older version of the platform, including:
 * <ul>
 * <li>Allows dynamic tint of it background via the background tint methods in
 * {@link android.support.v4.widget.CompoundButtonCompat}.</li>
 * <li>Allows setting of the background tint using {@link R.attr#buttonTint} and {@link R.attr#buttonTintMode}
 * .</li>
 * </ul>
 * 
 * <p>
 * This will automatically be used when you use {@link CheckBox} in your layouts. You should only need to
 * manually use this class when writing custom views.
 * </p>
 */
public class CheckBox extends android.widget.CheckBox implements TintableCompoundButton {

    private TintManager mTintManager;
    private CompoundButtonHelper mCompoundButtonHelper;
    private boolean mIsAnimationButton = true;

    final int[] checkOnDisableState = { android.R.attr.state_checked, -android.R.attr.state_enabled };
    final int checkOnDisableResId = R.drawable.btn_check_on_disabled_holo_light;
    final int[] checkOffDisableState = { -android.R.attr.state_checked, -android.R.attr.state_enabled };
    final int checkOffDisableResId = R.drawable.btn_check_off_disabled_holo_light;
    final int[] checkOnState = { android.R.attr.state_checked, android.R.attr.state_enabled };
    final int checkOnResId = R.drawable.btn_check_to_on_mtrl_007;
    final int[] checkOffState = { -android.R.attr.state_checked, android.R.attr.state_enabled };
    final int checkOffResId = R.drawable.btn_check_to_on_mtrl_000;
    final int checkOnkeyframeId = R.id.on;
    final int checkOffKeyframeId = R.id.off;
    final int checkToOnResId = R.drawable.btn_check_to_on_material_anim;
    final int checkToOffResId = R.drawable.btn_check_to_off_material_anim;
    private Drawable mAnimationButtonDrawable = null;
    private boolean mIsSupportTintDrawable = false;
    private int mColorControlActivated = 0;

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

    public CheckBox(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.checkboxStyle);
    }

    public CheckBox(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (mIsAnimationButton) {
            setAnimationButtonDrawable(mIsAnimationButton);
        } else {
            mTintManager = TintManager.get(context);
            mCompoundButtonHelper = new CompoundButtonHelper(this, mTintManager);
            mCompoundButtonHelper.loadFromAttributes(attrs, defStyleAttr);
        }
    }

    @Override
    public void setButtonDrawable(Drawable buttonDrawable) {
        super.setButtonDrawable(buttonDrawable);
        if (mCompoundButtonHelper != null && !mIsAnimationButton) {
            mCompoundButtonHelper.onSetButtonDrawable();
        }
    }

    @Override
    public void setButtonDrawable(@DrawableRes int resId) {
        setButtonDrawable(mTintManager != null ? mTintManager.getDrawable(resId)
                : getContext().getResources().getDrawable(resId));
    }

    @Override
    public int getCompoundPaddingLeft() {
        final int value = super.getCompoundPaddingLeft();
        return mCompoundButtonHelper != null ? mCompoundButtonHelper.getCompoundPaddingLeft(value) : value;
    }

    /**
     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
     * 
     * @hide
     */
    @Override
    public void setSupportButtonTintList(@Nullable ColorStateList tint) {
        if (mCompoundButtonHelper != null) {
            mCompoundButtonHelper.setSupportButtonTintList(tint);
        }
    }

    /**
     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
     * 
     * @hide
     */
    @Nullable
    @Override
    public ColorStateList getSupportButtonTintList() {
        return mCompoundButtonHelper != null ? mCompoundButtonHelper.getSupportButtonTintList() : null;
    }

    /**
     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
     * 
     * @hide
     */
    @Override
    public void setSupportButtonTintMode(@Nullable PorterDuff.Mode tintMode) {
        if (mCompoundButtonHelper != null) {
            mCompoundButtonHelper.setSupportButtonTintMode(tintMode);
        }
    }

    /**
     * This should be accessed from {@link android.support.v4.widget.CompoundButtonCompat}
     * 
     * @hide
     */
    @Nullable
    @Override
    public PorterDuff.Mode getSupportButtonTintMode() {
        return mCompoundButtonHelper != null ? mCompoundButtonHelper.getSupportButtonTintMode() : null;
    }

    public void setAnimationButtonDrawable(boolean isAnimation) {
        if (isAnimation) {
            int colorControlNormal = ThemeUtils.getThemeAttrColor(getContext(), R.attr.colorControlNormal);
            int colorControlActivated = ThemeUtils.getThemeAttrColor(getContext(), R.attr.colorControlActivated);
            int colorControlDisabled = ThemeUtils.getDisabledThemeAttrColor(getContext(),
                    R.attr.colorControlNormal);
            int colorControlActivateDisabled = ThemeUtils.getDisabledThemeAttrColor(getContext(),
                    R.attr.colorControlActivated);
            if (colorControlNormal == 0) {
                colorControlNormal = getContext().getResources().getColor(R.color.control_normal_color);
            }
            if (colorControlActivated == 0) {
                colorControlActivated = getContext().getResources().getColor(R.color.control_activated_color);
            }
            if (colorControlDisabled == 0) {
                colorControlDisabled = getContext().getResources().getColor(R.color.control_disabled_color);
            }
            if (colorControlActivateDisabled == 0) {
                colorControlActivateDisabled = getContext().getResources()
                        .getColor(R.color.control_activate_disabled_color);
            }

            setTintButtonDrawable(colorControlNormal, colorControlDisabled, colorControlActivated,
                    colorControlActivateDisabled);
        }
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        setAnimationButtonDrawable(View.VISIBLE == visibility);
    }

    public void setTintButtonDrawable(int colorStateList) {
        ColorStateList stateList = getContext().getResources().getColorStateList(colorStateList);
        if (stateList != null) {
            setTintButtonDrawable(stateList);
        }
    }

    public void setTintButtonDrawable(ColorStateList colorStateList) {
        mIsAnimationButton = true;
        int colorControlNormal = 0;
        int colorControlDisabled = 0;
        int colorControlActivated = 0;
        int colorControlActivateDisabled = 0;
        if (colorStateList.isStateful()) {
            colorControlNormal = colorStateList.getColorForState(checkOffState, colorStateList.getDefaultColor());
            colorControlDisabled = colorStateList.getColorForState(checkOffDisableState,
                    colorStateList.getDefaultColor());
            colorControlActivated = colorStateList.getColorForState(checkOnState, colorStateList.getDefaultColor());
            colorControlActivateDisabled = colorStateList.getColorForState(checkOnDisableState,
                    colorStateList.getDefaultColor());
        }
        setTintButtonDrawable(colorControlNormal, colorControlDisabled, colorControlActivated,
                colorControlActivateDisabled);
    }

    private void setTintButtonDrawable(int colorControlNormal, int colorControlDisabled, int colorControlActivated,
            int colorControlActivateDisabled) {
        final PorterDuff.Mode DEFAULT_MODE = PorterDuff.Mode.SRC_IN;
        final boolean isSupportTintDrawable = ThemeUtils.isSupportTintDrawable(getContext());
        TwsAnimatedStateListDrawable drawable = new TwsAnimatedStateListDrawable();
        Drawable checkOffDisableDrawable = getResources().getDrawable(checkOffDisableResId);
        Drawable checkOnDisableDrawable = getResources().getDrawable(checkOnDisableResId);
        Drawable checkOffDrawable = getResources().getDrawable(checkOffResId);
        Drawable checkOnDrawable = getResources().getDrawable(checkOnResId);

        if (isSupportTintDrawable) {
            checkOffDisableDrawable.setColorFilter(colorControlDisabled, DEFAULT_MODE);
            checkOnDisableDrawable.setColorFilter(colorControlActivateDisabled, DEFAULT_MODE);
            checkOffDrawable.setColorFilter(colorControlNormal, DEFAULT_MODE);
            checkOnDrawable.setColorFilter(colorControlActivated, DEFAULT_MODE);
        }

        drawable.addState(checkOffDisableState, checkOffDisableDrawable, 0);
        drawable.addState(checkOnDisableState, checkOnDisableDrawable, 0);
        drawable.addState(checkOffState, checkOffDrawable, checkOffKeyframeId);
        drawable.addState(checkOnState, checkOnDrawable, checkOnkeyframeId);
        AnimationDrawable toOnDrawable = (AnimationDrawable) getResources().getDrawable(checkToOnResId);
        AnimationDrawable toOffDrawable = (AnimationDrawable) getResources().getDrawable(checkToOffResId);

        if (isSupportTintDrawable) {
            toOnDrawable.setColorFilter(colorControlActivated, DEFAULT_MODE);
            toOffDrawable.setColorFilter(colorControlNormal, DEFAULT_MODE);
        }

        drawable.addTransition(checkOffKeyframeId, checkOnkeyframeId, toOnDrawable, false);
        drawable.addTransition(checkOnkeyframeId, checkOffKeyframeId, toOffDrawable, false);
        setButtonDrawable(drawable);
        mIsSupportTintDrawable = isSupportTintDrawable;
        mColorControlActivated = colorControlActivated;
        mAnimationButtonDrawable = drawable;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setRippleBackground(mIsSupportTintDrawable, mAnimationButtonDrawable, mColorControlActivated);
    }

    private void setRippleBackground(boolean isSupportTintDrawable, Drawable orgDrawable, int rippleColor) {
        if (orgDrawable != null && isSupportTintDrawable) {
            ColorStateList csl = createNormalStateList(rippleColor);
            final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
            final int drawableHeight = orgDrawable.getIntrinsicHeight();
            final int drawableWidth = orgDrawable.getIntrinsicWidth();
            final float scale = 0.3f;
            final float drawableScaleHeight = drawableHeight * scale;
            final float drawableScaleWidth = drawableWidth * scale;

            final int top;
            switch (verticalGravity) {
            case Gravity.BOTTOM:
                top = (int) (getHeight() - drawableHeight - drawableScaleHeight);
                break;
            case Gravity.CENTER_VERTICAL:
                top = (int) (((getHeight() - drawableHeight) / 2) - drawableScaleHeight);
                break;
            default:
                top = (int) (-drawableScaleHeight);
            }
            final int bottom = (int) (top + drawableHeight + drawableScaleHeight * 2);
            final int left = (int) (isLayoutRtl() ? getWidth() - drawableWidth - drawableScaleWidth
                    : -drawableScaleWidth);
            final int right = (int) (isLayoutRtl() ? getWidth() + drawableScaleWidth
                    : drawableWidth + drawableScaleWidth);

            TwsRippleDrawable rippleDrawable = new TwsRippleDrawable(csl, null, null,
                    TwsRippleDrawable.RIPPLE_STYLE_RING);
            rippleDrawable.twsSetHotspotBounds(left, top, right, bottom);
            setBackgroundDrawable(rippleDrawable);
        }
    }

    private ColorStateList createNormalStateList(int textColor) {
        // Now create a new ColorStateList with the default color
        final int[][] states = new int[1][];
        final int[] colors = new int[1];
        // Default state
        states[0] = EMPTY_STATE_SET;
        colors[0] = textColor;
        return new ColorStateList(states, colors);
    }
}