自定义圆环view 倒计时控件

自定义一个倒计时进度提示控件,适用于欢迎页面或广告页面倒计时退出等,逻辑很简单

以下内容仅是个人开发经验,欢迎指正~

话不多说,先上图


 
 
实现步骤
  • 第一步:在values文件夹下的布局文件attrs自定义属性
<declare-styleable name="MyTextView" >
    <attr name="progressBgColor" format="reference|color"/>
    <attr name="progressColor" format="reference|color"/>
    <attr name="progressLineWidth" format="dimension"/>
    <attr name="circleBgColr" format="reference|color"/> 
   <attr name="circleEndColor" format="reference|color"/>
    <attr name="totalTime" format="integer"/>
    <attr name="delayTime" format="integer"/>
</declare-styleable>

  • 第二步:代码实现
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import java.util.Timer;
import java.util.TimerTask;
 
/**
 * 自定义圆环view 倒计时控件
 */
 
public class CountDownButton extends Button implements View.OnClickListener{
 
    private Context mContext ;
    private onCountClickListener mCountClickListener ;
 
    private static final int DEFAULT_PROGRESS_BG_COLOR = Color.LTGRAY;
    private static final int DEFAULT_PROGRESS_COLOR = Color.BLUE ;
    private static final float DEFAULT_PROGRESS_LINE_WIDTH = 5 ;
    private static final int DEFAULT_CIRCLE_BG_COLOR = Color.DKGRAY ;
    private static final int DEFAULT_TOTAL_TIME = 5000 ;
    //定义刷新间隔时长ms
    private static final int DELAY = 500 ;
 
    private int mProgressBgColor = DEFAULT_PROGRESS_BG_COLOR ;
    private int mProgressColor = DEFAULT_PROGRESS_COLOR ;
    private float mProgressLineWidth = DEFAULT_PROGRESS_LINE_WIDTH ;
    private int mCircleBgColor = DEFAULT_CIRCLE_BG_COLOR ;
    private int mTotalTime = DEFAULT_TOTAL_TIME ;
    private int mDelayTime = DELAY ;
 
    private int mProgress ;
    private int mCountingVal ;
    private int mCountPer ;
    private int mCircleRadius ;
 
    //定义中心坐标
    private int mCenterX;
    private int mCenterY;
 
    //定义画笔、计时器等
    private Paint mPaint ;
    private Timer mTimer ;
    private Rect mRect ;
    private RectF mRectF ;
 
    //定义正在进行计时标志
    private boolean isCounting = false ;
 
    public CountDownButton(Context context) {
        this(context , null , 0);
    }
 
    public CountDownButton(Context context, AttributeSet attrs) {
        this(context, attrs , 0);
    }
 
    public CountDownButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context ;
        initView(attrs);
    }
 
    private void initView(AttributeSet attrs) {
        TypedArray mTypeArry = getContext().obtainStyledAttributes(attrs, R.styleable.MyTextView);
        mProgressBgColor = mTypeArry.getColor(R.styleable.MyTextView_progressBgColor , DEFAULT_PROGRESS_BG_COLOR) ;
        mProgressColor = mTypeArry.getColor(R.styleable.MyTextView_progressColor , DEFAULT_PROGRESS_COLOR) ;
        mProgressLineWidth = mTypeArry.getDimension(R.styleable.MyTextView_progressLineWidth , DEFAULT_PROGRESS_LINE_WIDTH);
        mCircleBgColor = mTypeArry.getColor(R.styleable.MyTextView_circleBgColr , DEFAULT_CIRCLE_BG_COLOR)  ;
        mTotalTime = mTypeArry.getInt(R.styleable.MyTextView_totalTime , DEFAULT_TOTAL_TIME) ;
        mDelayTime = mTypeArry.getInt(R.styleable.MyTextView_delayTime , DELAY) ;
        mTypeArry.recycle();
 
        mTimer = new Timer();
        mRect = new Rect();
        mRectF = new RectF();
        mPaint = new Paint();
 
        setOnClickListener(this);
    }
 
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取控件的宽高
        int width = getMeasuredWidth() ;
        int height = getMeasuredHeight();
 
        //确定为正方形布局
        if(width > height){
            height = width ;
        }else if(width < height){
            width = height;
        }
 
        //确定圆半径为控件宽/高一半
        mCircleRadius = width/2 ;
 
        //设置画布大小
        setMeasuredDimension(width,height);
 
    }
 
 
 
    @Override
    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);//不要继承父类的方法,避免部分属性设置不成功
        //获取正在绘制的控件边界
        getDrawingRect(mRect);
 
        //确定控件的中心坐标
        mCenterX = mRect.centerX();
        mCenterY = mRect.centerY();
 
        //开始绘制实心圆
        mPaint.setColor(mCircleBgColor);
        mPaint.setAntiAlias(true);//去锯齿
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(mCenterX , mCenterY ,mCircleRadius ,mPaint);
 
        //开始绘制进度条圆环
        mPaint.setColor(mProgressBgColor);
        mPaint.setStyle(Paint.Style.STROKE);//设置空心效果
        mPaint.setStrokeWidth(mProgressLineWidth);
        canvas.drawCircle(mCenterX , mCenterY ,mCircleRadius-mProgressLineWidth/2 ,mPaint);
 
        //绘制文字(必须使用getPaint())
        getPaint().setColor(getCurrentTextColor());
        getPaint().setTextAlign(Paint.Align.CENTER);
        getPaint().setAntiAlias(true);  //防锯齿
        float textY = mCenterY-(getPaint().descent()+getPaint().ascent())/2 ;
        canvas.drawText(getText().toString(), mCenterX , textY , getPaint());
 
        //开始绘制进度条
        mPaint.setColor(mProgressColor);
        mPaint.setStrokeWidth(mProgressLineWidth);
        mPaint.setStrokeCap(Paint.Cap.ROUND);//设置笔刷类型
        mRectF.set(mRect.left + mProgressLineWidth/2, mRect.top + mProgressLineWidth/2,
                mRect.right - mProgressLineWidth/2, mRect.bottom - mProgressLineWidth/2);
        canvas.drawArc(mRectF, -90, (float)mProgress* (360/(float)mCountPer), false, mPaint);
 
    }
 
 
    public int getProgressBgColor() {
        return mProgressBgColor;
    }
 
    public void setProgressBgColor(int mProgressBgColor) {
        this.mProgressBgColor = mProgressBgColor;
    }
 
    public int getProgressColor() {
        return mProgressColor;
    }
 
    public void setProgressColor(int mProgressColor) {
        this.mProgressColor = mProgressColor;
    }
 
    public float getmProgressWidth() {
        return mProgressLineWidth;
    }
 
    public void setProgressWidth(float mProgressWidth) {
        this.mProgressLineWidth = mProgressWidth;
    }
 
    public int getCircleBgColor() {
        return mCircleBgColor;
    }
 
    public void setCircleBgColor(int mCircleBgColor) {
        this.mCircleBgColor = mCircleBgColor;
    }
 
    public int getTotalTime() {
        return mTotalTime;
    }
 
    public void setTotalTime(int mTotalTime) {
        this.mTotalTime = mTotalTime;
    }
 
    public int getDelayTime() {
        return mDelayTime;
    }
 
    public void setDelayTime(int mDelayTime) {
        this.mDelayTime = mDelayTime;
    }
 
    public void cancle(){
        if(mTimer != null){
            mTimer.cancel();
        }
    }
 
    public void startTimer(){
        mCountPer = mTotalTime/mDelayTime;
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                mProgress ++;
                mCountingVal += mDelayTime;
                isCounting = true ;
                postInvalidate();
                if (mCountingVal >= mTotalTime) {
                    post(new Runnable() {
                        @Override
                        public void run() {
                            isCounting = false ;
                            cancle();
                            if(mCountClickListener != null){
                                mCountClickListener.onCountOverClick();
                            }
                        }
                    });
                }
            }
        }, mDelayTime, mDelayTime);
    }
 
    public void setOnCountClickListener(onCountClickListener mCountClickListener){
        this.mCountClickListener = mCountClickListener;
    }
 
    @Override
    public void onClick(View view) {
        if(mCountClickListener != null){
            if(isCounting){
                cancle();
                mCountClickListener.onCountingClick();
            } else{
                mCountClickListener.onCountOverClick();
            }
        }
    }
 
    public interface onCountClickListener{
        void onCountingClick();
        void onCountOverClick();
    };
}
  • 第三步:XML引用 根据需要配置各属性值
<cn.smartarvin.countdownview.widget.CountDownButton
    android:id="@+id/countdown2" 
    android:layout_width="200dp" 
    android:layout_height="200dp" 
    android:textColor="@android:color/white" 
    android:textSize="20sp" 
    android:text="跳过"   
    app:totalTime="5000"  
    app:progressLineWidth="10dp" 
   />
  • 第四步:代码中引用 根据需要在代码中配置各属性值
mTextView = (CountDownButton) findViewById(R.id.countdown2);
// mTextView.setTotalTime(5000);
// mTextView.setText("计时"); 
mTextView.startTimer();
mTextView.setOnCountClickListener(new
CountDownButton.onCountClickListener() {
@Override            
public void onCountingClick() { 
               Toast.makeText(MainActivity.this,"跳转",Toast.LENGTH_SHORT).show();  
}   
@Override 
public void onCountOverClick() { 
       Toast.makeText(MainActivity.this,"结束了",Toast.LENGTH_SHORT).show(); 
  }  
});

到此已完成倒计时控件的自定义以及引用过程,原理和逻辑很简单,自定义性灵活


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值