安卓数字倒数控件_Android自定义圆环倒计时控件

本文展示了如何在Android中创建一个自定义的圆环倒计时控件,通过属性动画实现倒计时功能。代码包括设置圆环颜色、宽度、文字样式等,并提供了XML布局和页面调用示例。
摘要由CSDN通过智能技术生成

本文实例为大家分享了Android自定义圆环倒计时控件的具体代码,供大家参考,具体内容如下

先来一张最终效果图:

主要思路: 在画渐变色圆环的时候,设置一个属性动画,根据属性动画的执行时长,来作为倒计时的时长.监听属性动画的进度,来达到 倒计时的目的.

二话不说,直接贴代码.具体实现思路都在注释上.

自定义属性:

主要代码:

import android.animation.ValueAnimator;

import android.content.Context;

import android.content.res.Resources;

import android.content.res.TypedArray;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.LinearGradient;

import android.graphics.Paint;

import android.graphics.Paint.FontMetricsInt;

import android.graphics.Rect;

import android.graphics.RectF;

import android.graphics.Shader;

import android.util.AttributeSet;

import android.util.TypedValue;

import android.view.View;

import android.view.animation.LinearInterpolator;

import com.daodaojk.myapplication.R;

public class CountDownProgressBar extends View {

/**

* 进度条最大值

*/

private int maxValue = 200;

/**

* 当前进度值

*/

private int currentValue ;

/**

* 每次扫过的角度,用来设置进度条圆弧所对应的圆心角,alphaAngle=(currentValue/maxValue)*360

*/

private float alphaAngle;

/**

* 底部圆弧的颜色,默认为Color.LTGRAY

*/

private int firstColor;

/**

* 进度条圆弧块的颜色

*/

private int secondColor;

/**

* 中间文字颜色(默认蓝色)

*/

private int centerTextColor = Color.BLUE;

/**

* 中间文字的字体大小(默认40dp)

*/

private int centerTextSize;

/**

* 圆环的宽度

*/

private int circleWidth;

/**

* 画圆弧的画笔

*/

private Paint circlePaint;

/**

* 画文字的画笔

*/

private Paint textPaint;

/**

* 是否使用渐变色

*/

private boolean isShowGradient = false;

/**

* 渐变圆周颜色数组

*/

private int[] colorArray = new int[]{Color.parseColor("#2773FF"),

Color.parseColor("#27C0D2"), Color.parseColor("#40C66E")};

private int duration;

private OnFinishListener listener;

private ValueAnimator animator;

public CountDownProgressBar(Context context) {

this(context, null);

}

public CountDownProgressBar(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public CountDownProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CountDownProgressBar,

defStyleAttr, 0);

int n = ta.getIndexCount();

for (int i = 0; i < n; i++) {

int attr = ta.getIndex(i);

switch (attr) {

case R.styleable.CountDownProgressBar_countDown_firstColor:

firstColor = ta.getColor(attr, Color.LTGRAY); // 默认底色为亮灰色

break;

case R.styleable.CountDownProgressBar_countDown_secondColor:

secondColor = ta.getColor(attr, Color.BLUE); // 默认进度条颜色为蓝色

break;

case R.styleable.CountDownProgressBar_countDown_centerTextSize:

centerTextSize = ta.getDimensionPixelSize(attr, (int) dip2px(40)); // 默认中间文字字体大小为40dp

break;

case R.styleable.CountDownProgressBar_countDown_circleWidth:

circleWidth = ta.getDimensionPixelSize(attr, (int) dip2px(6f)); // 默认圆弧宽度为6dp

break;

case R.styleable.CountDownProgressBar_countDown_centerTextColor:

centerTextColor = ta.getColor(attr, Color.BLUE); // 默认中间文字颜色为蓝色

break;

case R.styleable.CountDownProgressBar_countDown_isShowGradient:

isShowGradient = ta.getBoolean(attr, false); // 默认不适用渐变色

break;

default:

break;

}

}

ta.recycle();

circlePaint = new Paint();

circlePaint.setAntiAlias(true); // 抗锯齿

circlePaint.setDither(true); // 防抖动

circlePaint.setStrokeWidth(circleWidth);//画笔宽度

textPaint = new Paint();

textPaint.setAntiAlias(true);

textPaint.setDither(true);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

// 分别获取期望的宽度和高度,并取其中较小的尺寸作为该控件的宽和高,并且不超过屏幕宽高

int widthPixels = this.getResources().getDisplayMetrics().widthPixels;//获取屏幕宽

int heightPixels = this.getResources().getDisplayMetrics().heightPixels;//获取屏幕高

int width = MeasureSpec.getSize(widthMeasureSpec);

int hedight = MeasureSpec.getSize(heightMeasureSpec);

int minWidth = Math.min(widthPixels, width);

int minHedight = Math.min(heightPixels, hedight);

setMeasuredDimension(Math.min(minWidth, minHedight), Math.min(minWidth, minHedight));

}

@Override

protected void onDraw(Canvas canvas) {

int center = this.getWidth() / 2;

int radius = center - circleWidth / 2;

drawCircle(canvas, center, radius); // 绘制进度圆弧

drawText(canvas, center);

}

/**

* 绘制进度圆弧

*

* @param canvas 画布对象

* @param center 圆心的x和y坐标

* @param radius 圆的半径

*/

private void drawCircle(Canvas canvas, int center, int radius) {

circlePaint.setShader(null); // 清除上一次的shader

circlePaint.setColor(firstColor); // 设置底部圆环的颜色,这里使用第一种颜色

circlePaint.setStyle(Paint.Style.STROKE); // 设置绘制的圆为空心

canvas.drawCircle(center, center, radius, circlePaint); // 画底部的空心圆

RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius); // 圆的外接正方形

if (isShowGradient) {

// 绘制颜色渐变圆环

// shader类是Android在图形变换中非常重要的一个类。Shader在三维软件中我们称之为着色器,其作用是来给图像着色。

LinearGradient linearGradient = new LinearGradient(circleWidth, circleWidth, getMeasuredWidth()

- circleWidth, getMeasuredHeight() - circleWidth, colorArray, null, Shader.TileMode.MIRROR);

circlePaint.setShader(linearGradient);

}

circlePaint.setShadowLayer(10, 10, 10, Color.BLUE);

circlePaint.setColor(secondColor); // 设置圆弧的颜色

circlePaint.setStrokeCap(Paint.Cap.ROUND); // 把每段圆弧改成圆角的

alphaAngle = currentValue * 360.0f / maxValue * 1.0f; // 计算每次画圆弧时扫过的角度,这里计算要注意分母要转为float类型,否则alphaAngle永远为0

canvas.drawArc(oval, -90, alphaAngle, false, circlePaint);

}

/**

* 绘制文字

*

* @param canvas 画布对象

* @param center 圆心的x和y坐标

*/

private void drawText(Canvas canvas, int center) {

int result = ((maxValue - currentValue) * (duration / 1000) / maxValue); // 计算进度

String percent;

if (maxValue == currentValue) {

percent = "完成";

textPaint.setTextSize(centerTextSize); // 设置要绘制的文字大小

} else {

percent = (result / 60 < 10 ? "0" + result / 60 : result / 60) + ":" + (result % 60 < 10 ? "0" + result % 60 : result % 60);

// percent = result+"秒";

textPaint.setTextSize(centerTextSize+centerTextSize/3); // 设置要绘制的文字大小

}

textPaint.setTextAlign(Paint.Align.CENTER); // 设置文字居中,文字的x坐标要注意

textPaint.setColor(centerTextColor); // 设置文字颜色

textPaint.setStrokeWidth(0); // 注意此处一定要重新设置宽度为0,否则绘制的文字会重叠

Rect bounds = new Rect(); // 文字边框

textPaint.getTextBounds(percent, 0, percent.length(), bounds); // 获得绘制文字的边界矩形

FontMetricsInt fontMetrics = textPaint.getFontMetricsInt(); // 获取绘制Text时的四条线

int baseline = center + (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom; // 计算文字的基线 canvas.drawText(percent, center, baseline, textPaint); // 绘制表示进度的文字

}

/**

* 设置圆环的宽度

*

* @param width

*/

public void setCircleWidth(int width) {

this.circleWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, getResources()

.getDisplayMetrics());

circlePaint.setStrokeWidth(circleWidth);

//一般只是希望在View发生改变时对UI进行重绘。invalidate()方法系统会自动调用 View的onDraw()方法。

invalidate();

}

/**

* 设置圆环的底色,默认为亮灰色LTGRAY

*

* @param color

*/

public void setFirstColor(int color) {

this.firstColor = color;

circlePaint.setColor(firstColor);

//一般只是希望在View发生改变时对UI进行重绘。invalidate()方法系统会自动调用 View的onDraw()方法。

invalidate();

}

/**

* 设置进度条的颜色,默认为蓝色

*

* @param color

*/

public void setSecondColor(int color) {

this.secondColor = color;

circlePaint.setColor(secondColor);

//一般只是希望在View发生改变时对UI进行重绘。invalidate()方法系统会自动调用 View的onDraw()方法。

invalidate();

}

/**

* 设置进度条渐变色颜色数组

*

* @param colors 颜色数组,类型为int[]

*/

public void setColorArray(int[] colors) {

this.colorArray = colors;

//一般只是希望在View发生改变时对UI进行重绘。invalidate()方法系统会自动调用 View的onDraw()方法。

invalidate();

}

/**

* 按进度显示百分比,可选择是否启用数字动画

*

* @param duration 动画时长

*/

public void setDuration(int duration, OnFinishListener listener) {

this.listener = listener;

this.duration = duration + 1000;

if (animator != null) {

animator.cancel();

} else {

animator = ValueAnimator.ofInt(0, maxValue);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

currentValue = (int) animation.getAnimatedValue();

//一般只是希望在View发生改变时对UI进行重绘。invalidate()方法系统会自动调用 View的onDraw()方法。

invalidate();

if (maxValue == currentValue && CountDownProgressBar.this.listener != null) {

CountDownProgressBar.this.listener.onFinish();

}

}

});

animator.setInterpolator(new LinearInterpolator());

}

animator.setDuration(duration);

animator.start();

}

public interface OnFinishListener {

void onFinish();

}

public void setOnFinishListener(OnFinishListener listener) {

this.listener = listener;

}

public static int px2dip(int pxValue) {

final float scale = Resources.getSystem().getDisplayMetrics().density;

return (int) (pxValue / scale + 0.5f);

}

public static float dip2px(float dipValue) {

final float scale = Resources.getSystem().getDisplayMetrics().density;

return (dipValue * scale + 0.5f);

}

}

xml布局:

android:layout_width="match_parent"

android:layout_height="match_parent"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:orientation="vertical">

android:layout_width="match_parent"

android:text="开始"

android:id="@+id/btn_start"

android:layout_height="wrap_content" />

android:id="@+id/cpb_countdown"

android:layout_width="200dp"

android:layout_marginTop="100dp"

android:layout_gravity="center_horizontal"

app:countDown_centerTextSize="25dp"

app:countDown_circleWidth="4dp"

app:countDown_firstColor="@color/text_gray_ccc"

app:countDown_secondColor="@color/text_blue"

app:countDown_isShowGradient="true"

app:countDown_centerTextColor="#2395FF"

android:layout_height="200dp" />

页面调用:

package com.daodaojk.myapplication.ui;

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.Toast;

import com.daodaojk.myapplication.R;

import com.daodaojk.myapplication.view.CountDownProgressBar;

public class CountDownActivity extends AppCompatActivity {

private CountDownProgressBar cpb_countdown;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_count_down);

Button btn_start = findViewById(R.id.btn_start);

cpb_countdown = (CountDownProgressBar) findViewById(R.id.cpb_countdown);

btn_start.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

cpb_countdown.setDuration(10000, new CountDownProgressBar.OnFinishListener() {

@Override

public void onFinish() {

Toast.makeText(CountDownActivity.this, "完成了", Toast.LENGTH_SHORT).show();

}

});

}

});

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值