前几天公司需要做录音的波纹效果,原理很简单:定义一个记录所有同心圆半径的list,只要动态改变list的size,然后遍历之,并以每一个半径绘制圆(drawCircle), 通过在onDraw方法里面不停invalidate就可以了,代码如下:
package com.example.test.util; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import com.example.test.R; import java.util.ArrayList; import java.util.List; /** * Created by jisj on 6/1/16. */ public class RecordView extends View { public RecordView(Context context) { this(context, null, 0); } public RecordView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RecordView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; init(); } public void setIsWaving(boolean waving){ isWaving = waving; postInvalidate(); } private void init() { paint = new Paint(); paint.setColor(Color.parseColor("#ff6666")); paint.setAntiAlias(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(width = 600, height = 600); initOtherSize(); initStartCircle(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int count = radiusList.size(); //先绘制波纹 if(isWaving){ for (int i = 0; i < count; i++) { int radius = radiusList.get(i); float alpha = alphaList.get(i); paint.setAlpha((int) alpha); canvas.drawCircle(width / 2, height / 2, radius, paint); //宽度递增,透明度递减,宽度到最大时,透明度正好为0,singleAlpha保证了最外层的圆消失时不会突兀 if (alpha - singleAlpha >= 0) alphaList.set(i, alpha - singleAlpha); if (radius + 1 < this.width / 2) { radiusList.set(i, radius + 1); } } } //再绘制中间的图片 Drawable drawable = context.getResources().getDrawable(R.drawable.center_pic); drawable.setBounds((width - centerWidth) / 2, (height - centerWidth) / 2, (width + centerWidth) / 2, (height + centerWidth) / 2); drawable.draw(canvas); if(isWaving){ //如果没有达到最多的圆数,则加一个最内层的圆 if (count <= MAX_CIRCLE_COUNT) { //这里的width / (MAX_CIRCLE_COUNT * 7)是相邻波纹的半径差值 if (radiusList.size() <= 0 || radiusList.get(radiusList.size() - 1) == centerWidth / 2 + width / (MAX_CIRCLE_COUNT * 7)) { addInnerCircle(); } } //去掉最外层的圆 if (radiusList.size() > MAX_CIRCLE_COUNT) { radiusList.remove(0); alphaList.remove(0); } //执行onDraw的不断循环 postInvalidate(); } } private void initStartCircle() { clearDataList(alphaList); clearDataList(radiusList); alphaList.add(ORIGIN_ALPHA); radiusList.add(startRadius); } private void initOtherSize() { centerWidth = (int) (width * 0.54f); //startRadius比centerWidth略小,是为了保证起始圆环出场时藏在中心图片下面,不然会太突然 startRadius = centerWidth / 2 - 30; //圆环每增加1个像素,则透明度减低的值 singleAlpha = ORIGIN_ALPHA / ((width / 2 - startRadius)); } private void addInnerCircle() { alphaList.add(ORIGIN_ALPHA); radiusList.add(startRadius); } private void clearDataList(List list) { if (list.size() > 0) list.clear(); } private ArrayList<Float> alphaList = new ArrayList<Float>(); private ArrayList<Integer> radiusList = new ArrayList<Integer>(); private int width, height; private float singleAlpha = 1; //圆环每增加1个像素,则透明度减低的值 private int centerWidth; //中间固定图片的半径 private int startRadius; //起始圆环的半径 private boolean isWaving = false; private Paint paint; private Context context; private static final float ORIGIN_ALPHA = 150; //最内层圆环的透明度 private static final int MAX_CIRCLE_COUNT = 5; //最多的圆环数量 }
代码中用到的图片,是百度搜到的,如果有侵权。。。。。对不起啊大哥