4個(gè)小球

按照這里來設(shè)計(jì)的,效果比這里丑點(diǎn)。主要原因還是path畫的有點(diǎn)生硬,轉(zhuǎn)彎的時(shí)候不平滑。
http://www.itdecent.cn/p/138ad32540ce

就是簡單模仿下,所以細(xì)節(jié)未做優(yōu)化。這個(gè)小球的寬高和位置都是按照控件大小算的,所以這個(gè)控件需要固定的寬高,不要用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[]>();//最后要畫的小球的實(shí)時(shí)位置信息,數(shù)組長度為2,分別保存x和y的坐標(biāo)
    int[] startXPositioon = new int[4];//4個(gè)小球的起始位置,這里只有x的坐標(biāo),而y都是0
    int radius = 1;//小球的原始半徑
    float factorSacle = 0;//小球的實(shí)時(shí)放大比例
    //畫布被平移到正中心也就是0,0的位置,所以上邊的坐標(biāo)都是按照正中心為0,0計(jì)算的。
    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();
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,420評論 4 61
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,147評論 25 708
  • 我可憐嗎,沒錢吃飯,還欠一大筆債,好像是很可憐。但這些都是自己造成的。所以說自己不是可憐,是可恨。 還有希望嗎,堵...
    天青色_250d閱讀 153評論 0 0
  • 今天很多地方都下雪了,朋友圈里大家都在曬雪,嗯,我又很久沒有看到雪啦,有些懷念下雪的時(shí)光了。
    洮小夭_Amy閱讀 247評論 0 0
  • 即將開學(xué),明天就要報(bào)到上班啦,想想真是又興奮又好奇,第一次作為老師的開學(xué)季,隱約還能記起學(xué)生時(shí)代的味道,恩,這也是...
    想說就說2018閱讀 446評論 0 0

友情鏈接更多精彩內(nèi)容