Android自定义View实现APP启动页倒计时效果
作者:细嗅v蔷薇 时间:2022-11-14 05:42:54
Android自定义View实现APP启动页倒计时效果,供大家参考,具体内容如下
之前也是做过APP启动页的倒计时效果,但是只有文字变化,没有动画效果,这次通过使用自定义View控件来制作一个带有动画效果的倒计时。
倒计时效果的基本思路如下:
Canvas提供了绘制弧形的方法,drawArc(),使用这个方法通过定时刷新计算当前弧形的角度,就可以模拟出倒计时的动画效果,同时借助drawText()方法可以实现倒计时文字。
(1)继承View
(2)使用canvas的drawArc()来绘制弧形,模拟动画效果
(3)使用canvas的drawText()来绘制倒计时文字
(4)向外部(Activity或者Fragment)提供接口,倒计时结束之后通过接口告诉外部
具体看代码:
首先定义当前view的宽度和高度的默认值,并重写onMeasure()方法,否则在布局文件中即使使用wrap_content当前view也会布满全屏
//当前view高度和宽度的默认值
private static final int DEFAULT_WIDTH = 100;
private static final int DEFAULT_HEIGHT = 100;
定义三个变量,分别是倒计时总长度,当前剩余倒计时长度,以及剩余时间比例,根据这个比例绘制弧形划过的角度
private int countDownTime = 5000;//倒计时的时间,默认是5秒
private int countDownNow = 5000;//当前的时间,默认也是5秒
private float timeTatio = 1f;//剩余时间比例,默认为1
定义画笔以及向外部提供的接口
使用Android提供的倒计时类,如果不使用这个类,也可以通过thread+handler实现,初始化这个类需要传入两个参数,第一个参数是倒计时总长度,第二个参数是倒计时间隔,也就是每隔多长时间停止一次。这个类重写了两个方法,第一个方法是倒计时暂停的时候需要执行的操作,第二个方法是倒计时完全结束之后需要执行的操作,在这里,我设置了每隔10ms暂停一次,计算剩余时间的比例并重新绘制整个view,倒计时完全结束后通过接口告诉外部。
private Paint paint;
private ViewCountDownFinishListener viewCountDownFinishListener;
//倒计时,每隔100毫秒倒计时一次
private CountDownTimer countDownTimer = new CountDownTimer(countDownTime,10) {
@Override
public void onTick(long l) {
LogUtils.logI("倒计时:"+l);
countDownNow = (int) l;
//计算比例
timeTatio = (float) countDownNow / (float)countDownTime;
invalidate();
}
@Override
public void onFinish() {
countDownTimer.cancel();
if(viewCountDownFinishListener != null){
viewCountDownFinishListener.countDownFinish();
}
}
};
在构造方法中调用init()方法以启动倒计时
private void init(){
if(countDownTimer != null) {
countDownTimer.start();
}
}
//设置倒计时完成的接口
public void setViewCountDownFinishListener(ViewCountDownFinishListener viewCountDownFinishListener){
this.viewCountDownFinishListener = viewCountDownFinishListener;
}
重写onDraw()方法,根据
canvas.drawArc(float left,float top,float right,float bottom,float startAngle,float sweepAngle,boolean useCenter, Paint paint)
参数说明:
前四个参数表明当前的弧形所在的椭圆,只要设置椭圆宽度和高度一样,就是一个圆了,
startAngle是开始绘制的角度,以正右方向(X轴正方向)为0都,顺时针为正度数,逆时针为负度数,这里我设置从-90°(也就是Y轴负方向)开始,
sweep是指弧形划过的角度,这里我设置的是从0开始一直划过360度,刚好画一个圆,但是其实并没有完全到360度,因为我设置了每隔10ms执行一次,最后并不会完全是360度,但是非常接近,几乎看不出来。
useCenter表示是否连接到圆心,如果连接到圆心,就是扇形,这里需要弧形,就选择false
绘制完弧形后开始绘制倒计时文字,这个比较简单,就是计算倒计时剩余时间就可以了,然后绘制出来。
protected void onDraw(Canvas canvas) {
LogUtils.logI("onDraw()方法执行");
super.onDraw(canvas);
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setStrokeWidth(2);
paint.setAntiAlias(true);
//根据比例绘制一个扇形,也就是一个圆形
//当前的弧度
float currentRadian = 360 - 360 * timeTatio;
canvas.drawArc(10,10,60,60,-90,currentRadian,false,paint);
//绘制文字
paint.reset();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#3399ff"));
paint.setAntiAlias(true);
paint.setTextSize(30);
canvas.drawText(String.valueOf((int) (countDownNow/1000)),27,45,paint);
}
重写onMeasure()方法,为了将View显示在正确的位置上。
//重写onMeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(measureSpecHandler(widthMeasureSpec,DEFAULT_WIDTH),measureSpecHandler(heightMeasureSpec,DEFAULT_HEIGHT));
}
//计算高度和宽度的具体值
private int measureSpecHandler(int measureSpec,int defaultSize){
int result = defaultSize;
int specModel = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch(specModel){
case MeasureSpec.EXACTLY:
result = specSize;
break;
case MeasureSpec.AT_MOST:
result = Math.min(result,specSize);
break;
default:
result = defaultSize;
break;
}
return result;
}
定义接口,向外部提供倒计时完成的通知信息
//定义一个接口,当倒计时完成之后通知activity做出相应改变
public interface ViewCountDownFinishListener{
void countDownFinish();
}
在xml中直接使用:
<FrameLayout 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="com.fanjuan.project.wisdomclass.activity.ActivityMain">
<com.fanjuan.project.wisdomclass.view.CountDownView
android:id="@+id/cv_count_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp" />
</FrameLayout>
在activity中使用:
protected void initView() {
countDownView = findViewById(R.id.cv_count_down);
}
@Override
protected void initListener() {
super.initListener();
countDownView.setViewCountDownFinishListener(new CountDownView.ViewCountDownFinishListener() {
@Override
public void countDownFinish() {
ToastUtils.toastInfo("倒计时结束");
}
});
}
最后的效果:
来源:https://blog.csdn.net/ffa_ijj/article/details/79559325