自定义一个倒计时进度提示控件,适用于欢迎页面或广告页面倒计时退出等,逻辑很简单
以下内容仅是个人开发经验,欢迎指正~
话不多说,先上图
实现步骤
- 第一步:自定义属性
<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>
- 第二步:代码实现
package cn.smartarvin.countdownview.widget;
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;
import cn.smartarvin.countdownview.R;
/**
* Todo:倒计时控件
* Author:Arvin
* Date:2016/11/19 17:16
* Email:smartarvin199111@gmail.com
*/
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();
}
});
到此已完成倒计时控件的自定义以及引用过程,原理和逻辑很简单,自定义性灵活
谨以作为开发记录,如果有帮到您,记得点赞哦