版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】怎么在Android中自定义一个圆环倒计时控件
怎么在Android中自定义一个圆环倒计时控件?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面在下将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。自定义属性:<declare-styleable
name="CountDownProgressBar">
<attr
name="countDown_circleWidth"
format="dimension"
/>
<attr
name="countDown_centerTextSize"
format="dimension"
/>
<attr
name="countDown_betaAngle"
format="integer"
/>
<attr
name="countDown_firstColor"
format="color"
/>
<attr
name="countDown_secondColor"
format="color"
/>
<attr
name="countDown_centerTextColor"
format="color"
/>
<attr
name="countDown_isShowGradient"
format="boolean"
/>
</declare-styleable>主要代码: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();
}
/**
*
设置进度条的颜色,默认为蓝色<br>
*
*
@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布局:<?xml
version="1.0"
encoding="utf-8"?>
<LinearLayout
xmlns:android="/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="/apk/res-auto"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:text="开始"
android:id="@+id/btn_start"
android:layout_height="wrap_content"
/>
<com.daodaojk.myapplication.view.CountDownProgressBar
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=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 浅谈如何在课堂中促进学生的主体参与
- 架子工考试卷及答案
- 基坑支护、降水安全验收表
- 小学四年级下册数学期末测试试卷附答案(考试直接用)
- 人教版数学四年级下册期末测试卷【突破训练】
- 小学三年级上册数学期末测试卷【a卷】
- 教科版科学三年级下册第一单元《 物体的运动》测试卷及答案【夺冠系列】
- 小学数学试卷三年级上册数学期末测试卷必考题
- 人教版三年级上册数学期末测试卷含答案(突破训练)
- 人教版数学四年级下册期末测试卷加解析答案
- 埃森哲-流程优化方法论
- 四川省德阳市德阳二中教育集团2023-2024学年七年级下学期期中联考语文试题
- 股前内侧区解剖实验报告
- 国家质量监测应急预案
- 颅脑损伤ppt课件.ppt
- 涂料和油漆稀释剂配方
- GB 5340-85 可转位立铣刀
- 最全流程框架-美国生产力和质量中心APQC
- 一年级下册《体育与健康》教学计划
- 25M后张法预应力混凝土简支T型梁桥上部结构设计.doc
- JJF 1598-2016 气载放射性碘监测仪校准规范
评论
0/150
提交评论