Android 自定义View实现打钩(签到)的动画
发布日期:2021-06-29 11:46:18 浏览次数:3 分类:技术文章

本文共 3882 字,大约阅读时间需要 12 分钟。

先看效果图:

这里,我没有添加打钩的图片,而是单纯的用canvas来实现动画效果

中间的钩,我用了路径Path来进行描绘并实现它的动画效果。首先,这个钩由两条线段,三个顶点组成的,其实将这三个顶点作为参数传入Path对象中的lineTo()方法,再调用一下canvas.drawPath(),我们就可以得到图中这个钩的样式了

然后说说动画效果的实现,postInvalidateDelay()这个方法就很重要了,它能让onDraw()方法每隔一段时间被调用一次

所以,外部的圆环我们可以用drawArc()绘制圆弧的方式实现,每次调用onDraw()方法时绘制一定的角度,直到绘制出完整的圆环,就产生以上图中的动画效果

绘制圆环代码如下:

private int perAngle=5,currentAngle=0;     //每次绘制的角度;当前已经绘制的角度@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //......    //防止绘制的角度超过360度    if(currentAngle+perAngle>360)currentAngle=360;    else currentAngle+=perAngle;    canvas.drawArc(circleRectF,0,currentAngle,false,circlePaint);    //......    postInvalidateDelayed(5);}

最后是钩的动画实现,我首先计算了两条线段的斜率和截距:

//提供打钩的三个坐标点(radius/2,radius),(radius,(radius*3)/2),((radius*3)/2,radius/2)pathX=new int[]{radius/2,radius,(radius*3)/2};pathY=new int[]{radius,(radius*3)/2,radius/2};slopes=new float[pathX.length-1];intercepts=new float[pathX.length-1];//根据上面三个坐标点,得到两条线段,计算斜率和截距。for(int i=0;i

pathX,pathY (int[]) 记录三个顶点的坐标

slopes (float[]) 记录两条线段的斜率

intercepts (float[]) 记录两条线段的截距

 然后,我们设想一下,钩的移动方向一直是向右边的,也就是x轴的正方向,所以,我们从第一个顶点出发,每次调用onDraw()方法时,沿着上面的两个线段往右跑,即每次让x坐标增大一定的值,再通过y=ax+b,就可以计算出相应的y值。将(x,y)存入Path路径中,最后通过canvas.drawPath()将新保存的路径画出来,就可以实现动画效果

具体代码如下:

private int moveX=5,currentMoveX; //钩每次绘制的长度;目前移动到的位置@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //......    //绘制完圆环后,绘制打钩    //每次向x轴的正方向移动moveX的距离来实现动画效果    if(currentAngle>=360){        //防止绘制时出边界        if(currentMoveX+moveX>pathX[pathX.length-1])currentMoveX=pathX[pathX.length-1];        else currentMoveX+=moveX;        //判断目前已经绘制到哪一条线段上        for(int i=1;i

下面是自定义View的完整代码:

import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.RectF;import android.util.AttributeSet;import android.view.View;import androidx.annotation.Nullable;public class MyProgressFinishView extends View {    private Paint circlePaint;  //环的画笔    private RectF circleRectF;  //环的外切矩形    private Path path;          //钩的路径    private Paint pathPaint;    //钩的画笔    private int radius=200;     //环的半径    private int perAngle=5,currentAngle=0;     //每次绘制的角度;当前已经绘制的角度    private int[] pathX,pathY;    private float[] slopes; //每条直线的斜率    private float[] intercepts; //每条直线的截距    private int moveX=5,currentMoveX; //钩每次绘制的长度;目前移动到的位置    private boolean isFirstMeasure=true;    public MyProgressFinishView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        initPaint();    }    //初始化画笔    private void initPaint(){        circlePaint=new Paint();        circlePaint.setColor(Color.BLUE);        circlePaint.setStrokeWidth(8);        circlePaint.setStyle(Paint.Style.STROKE);        pathPaint=new Paint();        pathPaint.setColor(Color.BLUE);        pathPaint.setStrokeWidth(10);        pathPaint.setStyle(Paint.Style.STROKE);    }    //初始化钩的路径    private void initPath(){        circleRectF=new RectF(circlePaint.getStrokeWidth(),circlePaint.getStrokeWidth(),radius*2,radius*2);        path=new Path();        //提供打钩的三个坐标点(radius/2,radius),(radius,(radius*3)/2),((radius*3)/2,radius/2)        pathX=new int[]{radius/2,radius,(radius*3)/2};        pathY=new int[]{radius,(radius*3)/2,radius/2};        slopes=new float[pathX.length-1];        intercepts=new float[pathX.length-1];        //根据上面三个坐标点,得到两条线段,计算斜率和截距。        for(int i=0;i
360)currentAngle=360; else currentAngle+=perAngle; canvas.drawArc(circleRectF,0,currentAngle,false,circlePaint); //绘制完圆环后,绘制打钩 //每次向x轴的正方向移动moveX的距离来实现动画效果 if(currentAngle>=360){ //防止绘制时出边界 if(currentMoveX+moveX>pathX[pathX.length-1])currentMoveX=pathX[pathX.length-1]; else currentMoveX+=moveX; //判断目前已经绘制到哪一条线段上 for(int i=1;i

xml布局文件

 

转载地址:https://blog.csdn.net/zz51233273/article/details/107670430 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android 自定义View实现动画效果切换主题颜色
下一篇:Android 自定义View实现炮弹射击小游戏

发表评论

最新留言

不错!
[***.144.177.141]2024年04月05日 14时48分17秒