Wave动画效果
项目地址:Github
动画效果:
实现波浪wave效果,以及水位位置调整。
代码实现
外部形状
外部形状可以是圆形,三角形,整个图形的绘制区域由canvas决定
初始化paint
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| private void initBoarderPaint() { //默认的style是fill,填充的 mBoarderPain = new Paint(); mBoarderPain.setAntiAlias(true); mBoarderPain.setStyle(Paint.Style.STROKE);//描边 mBoarderPain.setStrokeWidth(DEFAULT_BOARD_WIDTH); mBoarderPain.setColor(Color.RED); }
private void initBgPaint() { //默认的style是fill,填充的 mBgPaint = new Paint(); mBgPaint.setAntiAlias(true); mBgPaint.setColor(getResources().getColor(R.color.voicebg)); }
|
在onDraw中绘制
1 2 3 4 5 6 7 8 9
| @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float boaderwidth = DEFAULT_BOARD_WIDTH;
canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, (getWidth() - boaderwidth) / 2f - 1f, mBoarderPain);//画边框 canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, getWidth() / 2f - boaderwidth, mBgPaint);//画圆形背景
}
|
怎么画波浪呢?
初始化paint
1 2 3 4 5 6
| private void initWavePaint() { mWavePain = new Paint(); mWavePain.setAntiAlias(true); mWavePain.setColor(getResources().getColor(R.color.voicefr)); updateWaveShader(); }
|
其中updateWaveShader,使用的着色器是BitmapShader。
1 2 3 4 5 6 7
| private void updateWaveShader() { if (getWaveBitmap() != null) { mWaveShader = new BitmapShader(getWaveBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);//x坐标repeat模式,y方向上最后一个像素重复 mWavePain.setShader(mWaveShader); } else { mWavePain.setShader(null); }
|
而getWaveBitmap()的任务是获得一个画有两个波浪的图形
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| private Bitmap getWaveBitmap() {//返回一个波形的图案,两条线
int wavecount = 1;//容纳多少个完整波形
int width = getMeasuredWidth(); int height = getMeasuredHeight(); Log.i("linlian", "width=" + width + " height=" + height); if (width > 0 && height > 0) {
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas waveLineCanvas = new Canvas(bitmap);
//坐标点数组,x从0-width,y=Asin(Wx+Q)+H // W = 2*PI/width // A = height // h = height // Q = 0 final int endX = width + 1; final int endY = height + 1; float W = (float) (2f * Math.PI * wavecount / width); float A = height / 10f;//波浪幅度在整体的10分之一 float H = height / 2;//默认水位在一半的位置 float[] waveY = new float[endX];
for (int x = 0; x < endX; x++) { waveY[x] = (float) (A * Math.sin(W * x)) + H; }
int xShift = width / 4; mWavePaint.setColor(getResources().getColor(R.color.wavebg)); for (int x = 0; x < endX; x++) { waveLineCanvas.drawLine(x, waveY[(x + xShift) % endX], x, endY, mWavePaint);// .:|:. 像这样画线 } mWavePaint.setColor(getResources().getColor(R.color.wavefr)); for (int x = 0; x < endX; x++) {
waveLineCanvas.drawLine(x, waveY[x], x, endY, mWavePaint);// .:|:. 像这样画线 }
return bitmap; } return null; }
|
设置好图形着色器之后,在view的onDraw方法上,添加
1 2 3 4 5 6 7 8 9 10 11
| @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float boaderwidth = DEFAULT_BOARD_WIDTH;
canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, (getWidth() - boaderwidth) / 2f - 1f, mBoarderPain);//画边框 canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, getWidth() / 2f - boaderwidth, mBgPaint);//画圆形背景
canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, getWidth() / 2f - boaderwidth, mWavePain);//画波浪图形 }
|
如何实现动画效果呢
通过属性动画来实现,改变waveXshift的值,从0到1变化,两秒,重复变化
1 2 3 4 5 6 7 8 9 10
| private void initAnimation() { mShaderMatrix = new Matrix(); ObjectAnimator waveXshiftAnimator = ObjectAnimator.ofFloat(this, "waveXshift", 0f, 1f); waveXshiftAnimator.setRepeatCount(ValueAnimator.INFINITE); waveXshiftAnimator.setDuration(2000); waveXshiftAnimator.setInterpolator(new LinearInterpolator()); mAnimatorset = new AnimatorSet(); mAnimatorset.play(waveXshiftAnimator);
}
|
属性变化的时候,重新绘制
1 2 3 4 5 6 7
| public void setWaveXshift(float mWaveXshift) { if (this.mWaveXshift != mWaveXshift) { this.mWaveXshift = mWaveXshift; //变化的是重新绘制view,实现动画效果 invalidate(); } }
|
在onDraw中,实现图像的水平移动 mWaveXshift * getWidth();
1 2 3 4 5 6 7 8 9 10 11
| if (mWaveShader != null) { if (mWavePaint.getShader() == null) { mWavePaint.setShader(mWaveShader); } float dx = mWaveXshift * getWidth(); mShaderMatrix.setTranslate(dx, 0);//平移波浪,实现推进效果 mWaveShader.setLocalMatrix(mShaderMatrix); } else { mWavePaint.setShader(null); } canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, getWidth() / 2f - boaderwidth, mWavePaint);//画波浪
|
重新实现的代码可以参考
https://github.com/lynn8570/VoiceView/blob/master/animlib/src/main/java/anim/lynn/voice/VoiceWave.java