自定义Switch背景带文字

 搞一个switch控件看了网上的很多都是用的selector去定义thumb 跟 track,这样可以改变它的背景跟小圆点。但没有办法设置文字,源码给了设置文字的方法,也只能设置再小圆点上。所以索性自己用一个View画一下背景跟文字,用动画来模拟一个switch控件。。。本来想搞个背景selector的但是这样没有了动画,感觉有点low。。。

 

 

 继承自View的switch控件,可以显示文字。

package com.yunhe.myapplication;

import android.animation.Animator;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by wuzhi.peng on 2019/7/4
 **/
public class CustomSwitch extends View implements ValueAnimator.AnimatorUpdateListener,ValueAnimator.AnimatorListener {

    //默认的宽高比例
    private static final float DEFAULT_WIDTH_HEIGHT_PERCENT = 0.38f;
    //动画最大的比例
    private static final float ANIMATION_MAX_FRACTION = 1;

    private int mWidth,mHeight;

    //画跑道型背景
    private Paint mBackgroundPain;
    //画背景上的字
    private Paint mDisaboleTextPaint;
    private Paint mEnableTextPaint;
    //画白色圆点
    private Paint mSlidePaint;

    //是否正在动画
    private boolean isAnimation;

    private ValueAnimator mValueAnimator;

    private float mAnimationFraction;

    private String openText;
    private String closeText;
    private int mOpenColor = Color.GREEN;
    private int mCloseColor = Color.GRAY;
    private int mCurrentColor = mCloseColor;

    //监听
    private OnCheckedChangeListener mCheckedChangeListener;

    private boolean isChecked;

    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);
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.CustomSwitch);
        openText = typedArray.getString(R.styleable.CustomSwitch_openText);
        closeText = typedArray.getString(R.styleable.CustomSwitch_closeText);
        mOpenColor = typedArray.getColor(R.styleable.CustomSwitch_openColor,Color.GREEN);
        mCloseColor = typedArray.getColor(R.styleable.CustomSwitch_closeColor,Color.GRAY);
        mCurrentColor = mCloseColor;
        typedArray.recycle();
        init();
    }

    private void init(){
        mBackgroundPain = new Paint();
        mBackgroundPain.setAntiAlias(true);
        mBackgroundPain.setDither(true);
        mBackgroundPain.setColor(Color.GRAY);
        mDisaboleTextPaint = new Paint();
        mDisaboleTextPaint.setAntiAlias(true);
        mDisaboleTextPaint.setDither(true);
        mDisaboleTextPaint.setStyle(Paint.Style.STROKE);
        mDisaboleTextPaint.setColor(Color.WHITE);
        mDisaboleTextPaint.setTextAlign(Paint.Align.CENTER);

        mEnableTextPaint = new Paint();
        mEnableTextPaint.setAntiAlias(true);
        mEnableTextPaint.setDither(true);
        mEnableTextPaint.setStyle(Paint.Style.STROKE);
        mEnableTextPaint.setColor(Color.WHITE);
        mEnableTextPaint.setTextAlign(Paint.Align.CENTER);

        mSlidePaint = new Paint();
        mSlidePaint.setColor(Color.WHITE);
        mSlidePaint.setAntiAlias(true);
        mSlidePaint.setDither(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width =  MeasureSpec.getSize(widthMeasureSpec);
        int height = (int) (width*DEFAULT_WIDTH_HEIGHT_PERCENT);
        setMeasuredDimension(width,height);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawBackground(canvas);
        drawSlide(canvas);
    }

    private void drawSlide(Canvas canvas){
        float distance = mWidth - mHeight;
        canvas.drawCircle(mHeight/2+distance*mAnimationFraction,mHeight/2,mHeight/3,mSlidePaint);
    }

    private void drawBackground(Canvas canvas){
        Path path = new Path();
        RectF rectF = new RectF(0,0,mHeight,mHeight);
        path.arcTo(rectF,90,180);
        rectF.left = mWidth-mHeight;
        rectF.right = mWidth;
        path.arcTo(rectF,270,180);
        path.close();
        mBackgroundPain.setColor(mCurrentColor);
        canvas.drawPath(path,mBackgroundPain);

        mDisaboleTextPaint.setTextSize(mHeight/2);
        mEnableTextPaint.setTextSize(mHeight/2);
        Paint.FontMetrics fontMetrics = mDisaboleTextPaint.getFontMetrics();
        float top = fontMetrics.top;
        float bottom = fontMetrics.bottom;
        int baseLine = (int) (mHeight/2 + (bottom-top)*0.3);

        if (!"".equals(openText)){
            //启用
            mDisaboleTextPaint.setAlpha((int) (255*mAnimationFraction));
            canvas.drawText(openText,mWidth*0.4f,baseLine,mDisaboleTextPaint);
        }

        if (!"".equals(closeText)){
            //启用
            mEnableTextPaint.setAlpha((int) (255*(1-mAnimationFraction)));
            canvas.drawText(closeText,mWidth*0.6f,baseLine,mEnableTextPaint);
        }

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                return true;
            case MotionEvent.ACTION_CANCEL:
                break;
            case MotionEvent.ACTION_UP:
                if (isAnimation){
                    return true;
                }
                if (isChecked){
                    startCloseAnimation();
                    isChecked = false;
                    if (mCheckedChangeListener!=null){
                        mCheckedChangeListener.onCheckedChanged(false);
                    }
                }else {
                    startOpeAnimation();
                    isChecked = true;
                    if (mCheckedChangeListener!=null){
                        mCheckedChangeListener.onCheckedChanged(true);
                    }
                }
                return true;


        }
        return super.onTouchEvent(event);
    }

    private void startOpeAnimation(){
        mValueAnimator = ValueAnimator.ofFloat(0.0f, ANIMATION_MAX_FRACTION);
        mValueAnimator.setDuration(500);
        mValueAnimator.addUpdateListener(this);
        mValueAnimator.addListener(this);
        mValueAnimator.start();
        startColorAnimation();
    }
    private void startCloseAnimation(){
        mValueAnimator = ValueAnimator.ofFloat(ANIMATION_MAX_FRACTION, 0.0f);
        mValueAnimator.setDuration(500);
        mValueAnimator.addUpdateListener(this);
        mValueAnimator.addListener(this);
        mValueAnimator.start();
        startColorAnimation();
    }

    private void startColorAnimation(){
        int colorFrom = isChecked?mOpenColor:mCloseColor; //mIsOpen为true则表示要启动关闭的动画
        int colorTo = isChecked? mCloseColor:mOpenColor;
        ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
        colorAnimation.setDuration(500); // milliseconds
        colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animator) {
                mCurrentColor = (int)animator.getAnimatedValue();
            }

        });
        colorAnimation.start();
    }



    //设置监听
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener){
        mCheckedChangeListener = listener;
    }

    public boolean isChecked() {
        return isChecked;
    }

    public void setChecked(boolean checked) {
        isChecked = checked;
        if (isChecked){
            mCurrentColor = mOpenColor;
            mAnimationFraction = 1.0f;
        }else {
            mCurrentColor = mCloseColor;
            mAnimationFraction = 0.0f;
        }
        invalidate();
    }

    @Override
    public void onAnimationStart(Animator animator) {
        isAnimation = true;
    }

    @Override
    public void onAnimationEnd(Animator animator) {
        isAnimation = false;
    }

    @Override
    public void onAnimationCancel(Animator animator) {
        isAnimation = false;
    }

    @Override
    public void onAnimationRepeat(Animator animator) {
        isAnimation = true;
    }

    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        mAnimationFraction = (float) valueAnimator.getAnimatedValue();
        invalidate();
    }

    public interface OnCheckedChangeListener{
        void onCheckedChanged(boolean isChecked);
    }
}


上面是自定义View的源码,比较简单就画了一个背景跟文字,还有一个小白点。 点击的时候做动画。设置了监听,可以监听选中状态。
attrs文件里面
<declare-styleable name="CustomSwitch">
    <attr name="closeText" format="string" />
    <attr name="openText" format="string" />
    <attr name="closeColor" format="color" />
    <attr name="openColor" format="color" />
</declare-styleable>

添加了几个属性,这个可以自己定义。

xml中的用法

<com.yunhe.myapplication.CustomSwitch
app:closeText="禁用"
app:openText="启用"
app:closeColor="#aaaaaa"
app:openColor="#ff0000"
android:layout_width="200dp"
android:layout_height="wrap_content"
/>
 
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值