Android OvalView实现

关于Android椭圆动画实现,非ValueAnimation方式

最近由于项目需要,实现了一个自定义椭圆动画view

OvalView

import androidx.annotation.Nullable;

public class OvalView extends View {

private int width;

private int height;

private int ovalWidth = 440;

private int ovalHeight = 230;

public RectF oval2 = new RectF(20, 100, ovalWidth, 100 + ovalHeight);


public OvalView(Context context) {
    super(context);
}

public OvalView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

public OvalView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    width = widthMeasureSpec;
    height = heightMeasureSpec;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    /*
     * 方法 说明 drawRect 绘制矩形 drawCircle 绘制圆形 drawOval 绘制椭圆 drawPath 绘制任意多边形
     * drawLine 绘制直线 drawPoin 绘制点
     */
    // 创建画笔
    Paint p = new Paint();
    p.setColor(Color.RED);// 设置红色
    p.setStyle(Paint.Style.STROKE);

    /* 设置渐变色 这个正方形的颜色是改变的 */
    Shader mShader = new LinearGradient(0, 0, 100, 100,
            new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW,
                    Color.LTGRAY}, null, Shader.TileMode.REPEAT); // 一个材质,打造出一个线性梯度沿著一条线。
    p.setShader(mShader);
    // p.setColor(Color.BLUE);
    canvas.drawArc(oval2, 180, 60, true, p);
    // 画弧,第一个参数是RectF:该类是第二个参数是角度的开始,第三个参数是多少度,第四个参数是真的时候画扇形,是假的时候画弧线


    canvas.drawOval(oval2, p);
    float[] mCurrentPosition = updatePosition1();

    if (mCurrentPosition[0] == 0 && mCurrentPosition[1] == 0) {
        canvas.drawCircle(20, 100 + (ovalHeight / 2), 20, p);
        //startAn1(180f, 100f, false);
    } else {
        canvas.drawCircle(mCurrentPosition[0], mCurrentPosition[1], 20, p);
    }


    float[] mCurrentPosition1 = updatePosition2();

    if (mCurrentPosition1[0] == 0 && mCurrentPosition1[1] == 0) {
        canvas.drawCircle(ovalWidth, 100 + (ovalHeight / 2), 20, p);
    } else {
        canvas.drawCircle(mCurrentPosition1[0], mCurrentPosition1[1], 20, p);
    }


}

private float[] updatePosition1() {
    float[] mCurrentPosition = new float[2];
    float cx = 20 + ovalWidth / 2;

    float cy = 100 + (ovalHeight / 2);
    if (countSweepAngle == 0) {
        return mCurrentPosition;
    }
    Path path = new Path();
    // path.addOval(oval2, Path.Direction.CW);
    path.addArc(oval2, startAngle, sweepAngle);
    //pathMeasure用来计算显示坐标
    PathMeasure pathMeasure = new PathMeasure(path, true);
    //float value = 90 * 2.9f;
    pathMeasure.getPosTan(pathMeasure.getLength() / 2, mCurrentPosition, null);
    Log.e("tuoyuan", mCurrentPosition[0] + "    " + mCurrentPosition[1]);
    return mCurrentPosition;
}

private float[] updatePosition2() {
    float[] mCurrentPosition = new float[2];
    float cx = 20 + ovalWidth / 2;

    float cy = 100 + (ovalHeight / 2);
    if (countSweepAngle1 == 0) {
        return mCurrentPosition;
    }
    Path path = new Path();
    // path.addOval(oval2, Path.Direction.CW);
    path.addArc(oval2, startAngle1, sweepAngle);
    //pathMeasure用来计算显示坐标
    PathMeasure pathMeasure = new PathMeasure(path, true);
    //float value = 90 * 2.9f;
    pathMeasure.getPosTan(pathMeasure.getLength() / 2, mCurrentPosition, null);
    Log.e("tuoyuan", mCurrentPosition[0] + "    " + mCurrentPosition[1]);
    return mCurrentPosition;
}

private final float sweepAngle = 10f;
private float startAngle = 180f;

private float countSweepAngle = 0f;

public void startAn1() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    startAnimation1();
                    startAnimation2();
                    Thread.sleep(300);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();

}

public void startAnimation1() {
    if (startAngle == 360f) {
        startAngle = 0f;
        countSweepAngle = 0f;
    } else if (startAngle == 180f && countSweepAngle == 180f) {
        startAngle = 180f;
        countSweepAngle = 0f;
    } else {
        startAngle += sweepAngle;
    }
    countSweepAngle += 10f;

    postInvalidate();
}

private float startAngle1 = 0f;

private float countSweepAngle1 = 0f;

public void startAnimation2() {
    if (startAngle1 == 360f && countSweepAngle1 == 180f) {
        startAngle1 = 0f;
        countSweepAngle1 = 0f;
    } else if (startAngle == 180f && countSweepAngle1 == 180f) {
        startAngle1 = 180f;
        countSweepAngle1 = 0f;
    } else {
        startAngle1 += sweepAngle;
    }
    countSweepAngle1 += 10f;

    postInvalidate();
}

}

后续源码会附上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜色无恒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值