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("倒计时结束");
            }
        });
    }

最后的效果:

Android自定义View实现APP启动页倒计时效果

来源:https://blog.csdn.net/ffa_ijj/article/details/79559325

标签:Android,启动页,倒计时
0
投稿

猜你喜欢

  • MyBatis通用Mapper和PageHelper的过程详解

    2022-09-29 16:17:03
  • 分析HashMap 的 JDK 源码

    2022-01-17 06:29:54
  • hibernate存取json数据的代码分析

    2022-01-18 15:00:08
  • Android实现透明动画

    2023-02-08 04:45:47
  • Java Comparable 和 Comparator 的详解及区别

    2023-07-05 10:41:44
  • Android开发实现ListView异步加载数据的方法详解

    2022-03-26 02:31:57
  • SpringBoot实现启动类的存放位置

    2021-12-02 21:13:21
  • idea无法切换分支报错问题及解决

    2023-12-14 22:39:26
  • Spring实战之XML与JavaConfig的混合配置详解

    2023-07-11 18:07:20
  • android分享纯图片到QQ空间实现方式

    2023-07-20 10:56:03
  • C#实现线程安全的简易日志记录方法

    2023-12-20 22:45:17
  • Android SQLite详解及示例代码

    2023-08-04 22:26:35
  • asp.net之生成验证码的方法集锦(一)

    2022-09-07 22:37:13
  • Java 十大排序算法之计数排序刨析

    2023-11-28 19:21:26
  • Java关于桶排序的知识点总结

    2023-12-06 03:18:04
  • Android简单实现弹幕效果

    2022-08-12 01:24:08
  • 浅析java实现数据加密问题

    2023-03-21 02:54:04
  • Android应用获取设备序列号的方法

    2021-07-17 00:55:31
  • spring框架cacheAnnotation缓存注释声明解析

    2022-04-14 17:13:05
  • SpringBoot解决Required String parameter xxx is not present问题

    2021-08-08 12:53:15
  • asp之家 软件编程 m.aspxhome.com