4个小球

按照这里来设计的,效果比这里丑点。主要原因还是path画的有点生硬,转弯的时候不平滑。
https://www.jianshu.com/p/138ad32540ce

就是简单模仿下,所以细节未做优化。这个小球的宽高和位置都是按照控件大小算的,所以这个控件需要固定的宽高,不要用wrap即可。

import java.util.ArrayList;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.View;

public class LaunchAnimaView extends View {

    public LaunchAnimaView(Context context) {
        super(context);
        initSomething();
    }

    public LaunchAnimaView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSomething();
    }

    public LaunchAnimaView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initSomething();
    }

    Paint paint = new Paint();
    int[] colors = { Color.RED, Color.BLUE, Color.YELLOW, Color.GREEN };//4种球的颜色
    float[] maxSacles = { 2, 1, 2, 1 };//4种球的最大方法比例
    ArrayList<Paint> paints = new ArrayList<Paint>();//保存4种画笔
    ArrayList<PathMeasure> measures = new ArrayList<PathMeasure>();//保存4跳路径的pathmeasure信息
    ArrayList<Path> paths = new ArrayList<Path>();//保存4跳路径
    ArrayList<float[]> positions = new ArrayList<float[]>();//最后要画的小球的实时位置信息,数组长度为2,分别保存x和y的坐标
    int[] startXPositioon = new int[4];//4个小球的起始位置,这里只有x的坐标,而y都是0
    int radius = 1;//小球的原始半径
    float factorSacle = 0;//小球的实时放大比例
    //画布被平移到正中心也就是0,0的位置,所以上边的坐标都是按照正中心为0,0计算的。
    private void initSomething() {
        for (int i = 0; i < 4; i++) {
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(colors[i]);
            paint.setStyle(Style.FILL);
            paints.add(paint);
        }
        paint.setColor(Color.BLACK);
        paint.setStyle(Style.STROKE);
        paint.setStrokeWidth(1);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);

        for (int i = 0; i < positions.size(); i++) {
            float[] pos = positions.get(i);
            canvas.drawCircle(pos[0], pos[1], radius * (1 + maxSacles[i] * factorSacle), paints.get(i));
//          canvas.drawPath(paths.get(i), paint);
        }

        canvas.restore();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        System.err.println("onLayout========================" + changed);
        makeMeasure();
    }

    private boolean haveMeasure = false;

    private void makeMeasure() {
        if (haveMeasure) {
            return;
        }
        haveMeasure = true;
        int halfWidth = getWidth() / 2;
        int halfHeigth = getHeight() / 2;
        radius = halfWidth / 16;
        startXPositioon[0] = -halfWidth / 2;
        startXPositioon[1] = -halfWidth / 4;
        startXPositioon[2] = halfWidth / 4;
        startXPositioon[3] = halfWidth / 2;
        Path path1 = new Path();
        path1.moveTo(-halfWidth / 2, 0);
        path1.cubicTo(-halfWidth / 2, 0, -halfWidth + radius * 4, -halfHeigth * 2 / 3, -halfWidth / 2 - radius * 2,
                -halfHeigth + radius * 4);
        path1.cubicTo(-halfWidth / 4, -halfHeigth + radius * 3, 0, -halfHeigth * 2 / 3, 0, 0);
        path1.moveTo(0, 0);

        Path path2 = new Path();
        path2.moveTo(-halfWidth / 4, 0);
        path2.cubicTo(-halfWidth / 4, 0, -halfWidth / 4 + radius, -halfHeigth * 2 / 3, halfWidth / 2,
                -halfHeigth * 2 / 3);
        path2.cubicTo(halfWidth / 2 + radius, -halfHeigth * 2 / 3 + radius * 3, halfWidth / 2 - radius, -halfHeigth / 3,
                0, 0);
        path2.moveTo(0, 0);

        Path path3 = new Path();
        path3.moveTo(halfWidth / 4, 0);
        path3.cubicTo(halfWidth / 4, 0, halfWidth / 4 - radius, halfHeigth * 2 / 3, 0, halfHeigth * 2 / 3);
        path3.cubicTo(-radius * 2, halfHeigth * 2 / 3 + radius * 2, -halfWidth + radius * 2, 0, -halfWidth / 2,
                -halfHeigth / 3);
        path3.cubicTo(-halfWidth / 2 + radius, -halfHeigth / 3 + radius, -halfWidth / 4, -halfHeigth / 4, 0, 0);

        Path path4 = new Path();
        path4.moveTo(halfWidth / 2, 0);
        path4.cubicTo(halfWidth / 2, 0, halfWidth + radius * 4, halfHeigth * 2 / 3, halfWidth / 2 - radius * 2,
                halfHeigth + radius * 4);
        path4.cubicTo(halfWidth / 2 - radius * 2, halfHeigth + radius * 4, -radius * 2, halfHeigth * 2 / 3, 0, 0);
        path4.moveTo(0, 0);

        paths.add(path1);
        paths.add(path2);
        paths.add(path3);
        paths.add(path4);
        for (Path path : paths) {
            measures.add(new PathMeasure(path, false));
            positions.add(new float[2]);
        }
        startTransX();
    }
    private void reset() {
        if (animator != null) {
            animator.cancel();
        }
        if (animator2 != null) {
            animator2.cancel();
        }
        for (int i = 0; i < positions.size(); i++) {
            float[] pos = positions.get(i);
            pos[0] = 0;
            pos[1] = 0;
        }
        factorSacle = 0;
        postInvalidate();
    }
    public void startTransX() {
        reset();
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(1000);
        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = animation.getAnimatedFraction();
                for (int i = 0; i < measures.size(); i++) {
                    float[] pos = positions.get(i);
                    pos[0] = startXPositioon[i] * value;
                }
                postInvalidate();
                if(value>=1) {
                    startMove();
                }
            }
        });
        animator.start();
    }

    private void startMove() {
        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.setDuration(2000);
        animator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = animation.getAnimatedFraction();
                for (int i = 0; i < measures.size(); i++) {
                    PathMeasure pathMeasure = measures.get(i);
                    float[] pos = positions.get(i);
                    pathMeasure.getPosTan(value * pathMeasure.getLength(), pos, null);
                }
                if (value < 0.66) {
                    factorSacle = value / 0.66f;
                } else {
                    factorSacle = (1 - value) / (1 - 0.66f);
                }

                postInvalidate();
            }
        });
        animator.start();
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 14,821评论 4 61
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 177,245评论 25 709
  • 我可怜吗,没钱吃饭,还欠一大笔债,好像是很可怜。但这些都是自己造成的。所以说自己不是可怜,是可恨。 还有希望吗,堵...
    天青色_250d阅读 1,234评论 0 0
  • 今天很多地方都下雪了,朋友圈里大家都在晒雪,嗯,我又很久没有看到雪啦,有些怀念下雪的时光了。
    洮小夭_Amy阅读 1,652评论 0 0
  • 即将开学,明天就要报到上班啦,想想真是又兴奋又好奇,第一次作为老师的开学季,隐约还能记起学生时代的味道,恩,这也是...
    想说就说2018阅读 3,025评论 0 0

友情链接更多精彩内容