csdn上关于水波纹的demo很多,实现方法也很多,这里我是根据正弦函数生成的,及供参考。。。。
上代码:
/*绘图*/
private Paint paint ; // 画波浪的画笔
private Paint mCirclePaint; // 画圆的画笔
private Paint mTextPaint ; // 画字的画笔
private Canvas mCanvas; // 画布
private Bitmap mBitmap; //
int time = 0; // 控制波浪波动的快慢
int width ,height;
private int mPercent ; // 百分比
private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);//设置mode 为XOR
private String mText;
private float mTextSize;
private int mTextColor;
private boolean mTextVisible = true;
private int mWaveBackgroud; // 波浪颜色
private int mWaveBottomColor; // 波浪底色
public WaveView1(Context context) {
super(context);
}
public WaveView1(Context context, AttributeSet attrs) {
super(context, attrs,0);
initView(attrs);
}
public WaveView1(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(attrs);
}
public void initView(AttributeSet attrs){
TypedArray typedArray = getContext().obtainStyledAttributes(attrs,R.styleable.WaveView1);
mWaveBottomColor = typedArray.getColor(R.styleable.WaveView1_waveBottomColor,Color.parseColor("#88dddddd"));
mWaveBackgroud = typedArray.getColor(R.styleable.WaveView1_waveBackgroud,Color.parseColor("#53ff42"));
mText = typedArray.getString(R.styleable.WaveView1_text);
mTextColor = typedArray.getColor(R.styleable.WaveView1_textColor,Color.parseColor("#000000"));
mTextSize = typedArray.getDimension(R.styleable.WaveView1_textSize,24);
mTextVisible = typedArray.getBoolean(R.styleable.WaveView1_textVisible,true);
typedArray.recycle();
paint = new Paint();
paint.setColor(mWaveBottomColor);
// 设置宽度
paint.setStrokeWidth(3);
// 设置样式
paint.setStyle(Paint.Style.FILL);
// 抗锯齿
paint.setAntiAlias(true);
mCirclePaint = new Paint();
mCirclePaint.setColor(mWaveBackgroud);
mCirclePaint.setAntiAlias(true);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setTextSize(mTextSize);
mTextPaint.setColor(mTextColor);
Log.d(TAG,"***** initView ******");
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
}
// TODO 放在相对布局中 width 和 height 等于0 ????????
if (width == 0 || height == 0){
width = 500;
height = 500;
}
Log.d(TAG, "width == " + width + " height == " + height);
mBitmap = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888); //生成一个bitmap
mCanvas = new Canvas(mBitmap);//讲bitmp放在我们自己的画布上,实际上mCanvas.draw的时候 改变的是这个bitmap对象
setMeasuredDimension(width, height);
}
先是这些准备工作,画笔画布,自定义属性等等。。。
最主要的还是onDraw方法:
@Override
protected void onDraw(Canvas canvas) {
// TODO 周期性变化
time += 20;
// time ++ ;
if (time == 360){ // TODO 三角函数知识 周期性 不解释。。。
time = 0;
}
int pointX = 0;
int pointY = 0;
// TODO 清除掉图像,不然波纹交界处有阴影 加上颜色会变得淡一些
mBitmap.eraseColor(Color.parseColor("#00000000"));
mCanvas.drawCircle(width/2,height/2,height/2,mCirclePaint);
// TODO 设置重叠模式
paint.setXfermode(mMode);
if (mPercent == 0){
// 进度为 0 不画
}else if ( mPercent >= 100){
// 全部画满
while (pointX < width){
pointY = 0;
mCanvas.drawLine(pointX,pointY,pointX,height,paint);
pointX ++;
}
}else{
while (pointX < width){
pointY = (int) (15 * Math.sin((pointX - time)* Math.PI / 180)) + (height - height * mPercent/100);
mCanvas.drawLine(pointX,pointY,pointX,height,paint);
pointX ++;
}
}
postInvalidateDelayed(100);
canvas.drawBitmap(mBitmap,0,0,null);
// TODO 画字
if (mTextVisible){
canvas.drawText(mPercent + " %",width/2 - 12,height/2 + 12,mTextPaint);
}
super.onDraw(canvas);
}
整个的原理就是根据正弦函数的周期性有规律的波动,如果想调节波动的速率,有两个地方:
1. time参数,time参数越大,函数变化越明显,正弦函数得知识应该都还没忘吧。。。
2.
postInvalidateDelayed(100);
这个地方是设置view重绘的时间,最好还是时间长一点吧,在波动的过程中一直在重绘
当然设置view的动态效果可以有多种,可以用Handler 或者 Thread + runnable,我的源码里也有,可以参考参考
还有关于 PorterDuffXfermode 设置遮盖模式,自己用代码实现一下,很好理解:
源码地址:http://download.youkuaiyun.com/detail/qq55214/9630956