在上次【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(); } }); } } }
编译运行: