线的缩放效果

在上次【https://www.cnblogs.com/webor2006/p/9140811.html】中实现了系统动画中缩放圆的效果,这次还是实现一系列动画的效果中其中一个,先来看下系列动画:

要实现的是线条的绽放效果,如下:

静态视图绘制:

同样的先来绘制出静态的线条效果,先新建一个View:

其实现思路就是先绘制出5条静态的竖线,如下:

然后再对每针线条进行缩放控制达到我们最终想要的效果,所以第一步先来绘制静态图,如何绘制呢?canvas.drawRect()之前咱们用过刚好可以绘制一个矩形,用它是不是合适呢?试试,怎么绘制搞定了,接下来就想多根线条需要怎么来实现?有两种方案:

1、绘制的时候来改变Rect中的left的值。

2、利用移动画布的方式不改变Rect来达到多根线的效果。【采用它!】

具体来实现一下,需要绘制5根线条,则用一个for循环既可:

其中要绘制一根线需要确定Rect的左上右下的值,上下这个好确定,先确定整个高度,因为线条未来还要进行收缩处理,所以其线条的高度肯定不能够画满,这里定成整个View高度的一半,如下:

整个线条的高度确定之后,那Rect的top和bottom就可以确定了,如下:

所以:

接着就要确定RectF的left和right值了,同样的也是需要确定线条的粗细,这里用一个相对的值,如下:

所以left和right就可以确定了,如下:

所以:

接着就得每绘制一次,画布就得平移一下来达到多个线条的效果,那如何移动画布呢?就是根据循环的情况去修改x的值既可,如下:

为了能看到绘制的位置咱们给View增加一个背景色,如下:

编译运行:

但是发现一个小细节有点问题,线角不是圆的呀:

那有木有现成画带圆角的矩形的呢?原来有的,如下:

再次运行:

实现动画:

首先先来实现这种效果:

其实也就是按一定的时间依次对线条进行Y轴缩放处理,而这里可以采用画布的缩放来达到效果,如下:

其动画实现跟上一次【https://www.cnblogs.com/webor2006/p/9140811.html】处理多个缩放圆的效果差不多,还是用ValueAnimator来进行,首先先定义一个数组来存放每个线条缩放的比例,默认是1.0f,如下:

然后再定义另一个数组,用来控制每个线条执行动画的延迟时间,如下:

然后开启动画,如下:

接着就得来处理绘制了,得根据不同的线程的情况动态进行缩放,如下:

编译运行:

其余效果快速实现:

接着剩下的效果实现就比较简单了,只要调整其延迟时间的顺序既可,下面先来实现它:

调整延迟顺序如下:

编译运行:

最后再来实现“卡拉OK”播放的效果,这次需调整延迟时间之外,其动画的播放总时长也得进行修改,如下:

/**
 * 线的缩放效果---其余效果实现
 */
public class LinesView extends View {

    //constants
    /* 用来控制每个线条的缩放 */
    private static final float[] SCALES = new float[]{1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
    /* 根据不同的效果来控制某个线条的播放延时 */
    private static final int[] DELAYS = new int[]{770, 290, 280, 740, 500};
    /* 修改动画执行一次的时间 */
    private static final int[] DURATIONS = new int[]{1260, 430, 1010, 730, 500};

    //varibaels
    private Paint paint;

    public LinesView(Context context) {
        this(context, null);
    }

    public LinesView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.WHITE);
        prepareAnimators();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制5个线条
        int x = getWidth() / 11;
        int y = getHeight() / 2;
        for (int i = 0; i < 5; i++) {
            canvas.save();
            canvas.translate((1 + i * 2) * x, y);//利用移动画布来达到绘制多个线条的效果
            //利用画布缩放来实现视图的高度变化
            canvas.scale(1.0f, SCALES[i]);
            RectF rectF = new RectF(-x / 2, -y / 2, x / 2, y / 2);
            canvas.drawRoundRect(rectF, 5, 5, paint);
            canvas.restore();
        }
    }

    private void prepareAnimators() {
        for (int i = 0; i < 5; i++) {
            final int index = i;
            ValueAnimator valueAnimator = ValueAnimator.ofFloat(1, 0.5f);
            valueAnimator.setDuration(DURATIONS[i]);
            valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
            valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
            valueAnimator.setStartDelay(DELAYS[i]);
            valueAnimator.start();
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    SCALES[index] = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
        }
    }
}

编译运行:

posted on 2018-08-05 20:19  cexo  阅读(321)  评论(0编辑  收藏  举报

导航