android实现圆环倒计时控件
作者:旺仔哥 发布时间:2021-12-15 20:55:54
标签:android,倒计时
本文实例为大家分享了android实现圆环倒计时控件的具体代码,供大家参考,具体内容如下
1.自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 倒计时控件属性 -->
<declare-styleable name="CountDownView">
<!--颜色-->
<attr name="ringColor" format="color" />
<!-- 进度文本的字体大小 -->
<attr name="progressTextSize" format="dimension" />
<!-- 圆环宽度 -->
<attr name="ringWidth" format="float" />
<!--进度文本颜色-->
<attr name="progressTextColor" format="color"/>
<!--倒计时-->
<attr name="countdownTime" format="integer"/>
</declare-styleable>
</resources>
2.自定义view
public class CountDownView extends View {
//圆环颜色
private int mRingColor;
//圆环宽度
private float mRingWidth;
//圆环进度值文本大小
private int mRingProgessTextSize;
//宽度
private int mWidth;
//高度
private int mHeight;
private Paint mPaint;
//圆环的矩形区域
private RectF mRectF;
//
private int mProgessTextColor;
private int mCountdownTime;
private float mCurrentProgress;
ValueAnimator valueAnimator;
/**
* 监听事件
*/
private OnCountDownListener mListener;
public CountDownView(Context context) {
this(context, null);
}
public CountDownView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CountDownView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// init();
/**
* 获取相关属性值
*/
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CountDownView);
mRingColor = typedArray.getColor(R.styleable.CountDownView_ringColor, context.getResources().getColor(R.color.colorAccent));
mRingWidth = typedArray.getFloat(R.styleable.CountDownView_ringWidth, 40);
mRingProgessTextSize = typedArray.getDimensionPixelSize(R.styleable.CountDownView_progressTextSize, 20);
mProgessTextColor = typedArray.getColor(R.styleable.CountDownView_progressTextColor, context.getResources().getColor(R.color.colorAccent));
mCountdownTime = typedArray.getInteger(R.styleable.CountDownView_countdownTime, 60);
typedArray.recycle();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setAntiAlias(true);
this.setWillNotDraw(false);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
mRectF = new RectF(0 + mRingWidth / 2, 0 + mRingWidth / 2,
mWidth - mRingWidth / 2, mHeight - mRingWidth / 2);
}
/**
* 设置倒计时间 单位秒
* @param mCountdownTime
*/
public void setCountdownTime(int mCountdownTime) {
this.mCountdownTime = mCountdownTime;
invalidate();
}
// public CountDownView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
// super(context, attrs, defStyleAttr, defStyleRes);
// }
/**
* 动画
* @param countdownTime
* @return
*/
private ValueAnimator getValueAnimator(long countdownTime) {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 100);
valueAnimator.setDuration(countdownTime);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setRepeatCount(0);
return valueAnimator;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
*圆环
*/
//颜色
mPaint.setColor(mRingColor);
//空心
mPaint.setStyle(Paint.Style.STROKE);
//宽度
mPaint.setStrokeWidth(mRingWidth);
canvas.drawArc(mRectF, -90, mCurrentProgress - 360, false, mPaint);
//绘制文本
Paint textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setTextAlign(Paint.Align.CENTER);
String text = mCountdownTime - (int) (mCurrentProgress / 360f * mCountdownTime) + "";
textPaint.setTextSize(mRingProgessTextSize);
textPaint.setColor(mProgessTextColor);
//文字居中显示
Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();
int baseline = (int) ((mRectF.bottom + mRectF.top - fontMetrics.bottom - fontMetrics.top) / 2);
canvas.drawText(text, mRectF.centerX(), baseline, textPaint);
}
/**
* 开始倒计时
*/
public void startCountDown() {
valueAnimator = getValueAnimator(mCountdownTime * 1000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float i = Float.valueOf(String.valueOf(animation.getAnimatedValue()));
mCurrentProgress = (int) (360 * (i / 100f));
invalidate();
}
});
valueAnimator.start();
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//倒计时结束回调
if (mListener != null) {
mListener.countDownFinished();
}
}
});
}
/**
* 停止倒计时
*/
public void stopCountDdwn(){
valueAnimator.cancel();
}
public void setOnCountDownListener(OnCountDownListener mListener) {
this.mListener = mListener;
}
}
3.布局文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<demo.com.countdowndemo.CountDownView
android:id="@+id/countDownView"
android:layout_width="50dp"
android:layout_height="50dp"
app:countdownTime="5"
app:ringWidth="2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
4.Activity
public class MainActivity extends AppCompatActivity {
CountDownView countDownView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
countDownView = findViewById(R.id.countDownView);
countDownView.setOnCountDownListener(new OnCountDownListener() {
@Override
public void countDownFinished() {
//倒计时结束
//countDownView.setCountdownTime(10);
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);
}
});
countDownView.startCountDown();
countDownView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
countDownView.stopCountDdwn();
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);
}
});
}
}
来源:https://blog.csdn.net/wangwangli6/article/details/79933356


猜你喜欢
- 配置绑定所谓配置绑定”就是把配置文件中的值与 JavaBean 中对应的属性进行绑定。通常,我们会把一些配置信息(例如,
- 如下所示://StreamRead来读取一个文件 using (StreamReader sr = new StreamRea
- 前言WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏
- 一、创建字符串创建字符串的方式有很多种,当是常见的一般就三种1. 直接赋值(常用)String str = "hello worl
- 本文为大家分享了Android基础控件RadioGroup的使用,供大家参考,具体内容如下1.简单介绍RadioGroup可以提供几个选项供
- 本文实例讲述了Android编程之短信列表的时间显示。分享给大家供大家参考,具体如下:Android的短信的时间的显示做的很精细,首先保存在
- 在PDF文档中,图层可以使部分内容选择性地被隐藏或显示。通过添加图层,我们可以将文本、图片、表格等元素精确定位于页面指定位置,并可将这些元素
- maven简介及优势 maven是一个项目构建和管理的工具,提供了帮助管理 构建、文档、报告
- 本文是vhr系列的第十二篇,项目地址 https://github.com/lenve/vhr邮件发送也是一个老生常谈的问题了,代码虽然简单
- 本文实例为大家分享了Android App获取屏幕旋转角度的具体代码,供大家参考,具体内容如下一、获取屏幕旋转角度的方法是:int rota
- 什么是过滤器过滤器 Filter 基于 Servlet 实现,过滤器的主要应用场景是对字符编码、跨域等问题进行过滤。Servlet 的工作原
- 今天分享的是用系统自带的相机实现一键拍照功能。public class MainActivity extends AppCompatActi
- 问题有时候有些操作是防止用户在一次响应结束中再响应下一个。但有些测试用户就要猛点,狂点。像这种恶意就要进行防止。比如在客户端中,一些按钮一般
- Java7中文件IO发生了很大的变化,专门引入了很多新的类:import java.nio.file.DirectoryStream;imp
- 本章先讲解Java随机数的几种产生方式,然后通过示例对其进行演示。广义上讲,Java中的随机数的有三种产生方式:(01). 通过System
- 概念介绍什么是死信死信可以理解成没有被正常消费的消息,在RabbitMQ中以下几种情况会被认定为死信:消费者使用basic.reject或b
- 由于byte是一个8位字节所以可以用它来存放数组为8的boolean数组,这些在通信协议会经常用到。这里给出一个java代码对其互相转换的。
- 学习大佬们开发安全小工具,打包jar解决错误: 找不到或无法加载主类 main1 Maven方式遇到报错”找不到或无法加载主类 main“解
- 现在很多app的支付、输入密码功能,都已经开始使用自定义数字键盘,不仅更加方便、其效果着实精致。下面带着大家学习下,如何 * 微信的数字键盘,
- 我就废话不多说了,大家还是直接看代码吧~import com.alibaba.fastjson.JSON;import java.util.