自定义一个倒计时进度提示控件,适用于欢迎页面或广告页面倒计时退出等,逻辑很简单
以下内容仅是个人开发经验,欢迎指正~
话不多说,先上图
实现步骤
- 第一步:在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(); } });
到此已完成倒计时控件的自定义以及引用过程,原理和逻辑很简单,自定义性灵活