话不多说,先上效果图
下面说说原理,基本原理就是不停的绘制一条正弦曲线,曲线方程为y=A*Sin(w*x+fai)+k
参数A是波浪振幅,A越大,波浪高度越大,基线K是就能直接表现进度,会随着进度的增大而减小
w参数很重要,表示了图像的紧密程度,设置的小一点就会让图像较为平缓,初相fai,表示当X等于0时候的第一个位置
在代码中不停的变化这个参数,就可以让这条曲线动起来。
这个控件里面主要还是涉及三角函数的问题,不是很清楚的可以再研究研究
这些清楚了,那么代码就好办了
package customiew; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.View; /** * 水波纹特效,使用正弦函数 */ public class SinWaterwaveView extends View { private float x,y; //正弦函数的参数 y=A*Sin(w*x+fai)+k private float w=(float) (Math.PI/128),fai=0,A=8,k=0; //进度,单位是% private float progress=0; //view的宽高 private float width,height; //路径 private Path mPath; //波纹画笔和文字画笔 private Paint mPaint,textPaint; public SinWaterwaveView(Context context) { super(context); // TODO Auto-generated constructor stub init(); } public SinWaterwaveView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // TODO Auto-generated constructor stub init(); } public SinWaterwaveView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub init(); } private void init() { mPaint=new Paint(); textPaint=new Paint(); textPaint.setColor(0xffffffff); mPaint.setAntiAlias(true); mPaint.setColor(0xaa000077); mPaint.setStyle(Paint.Style.FILL); mPaint.setStrokeWidth(5.0f); mPaint.setTextSize(20); mPath=new Path(); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub mPath.reset(); mPath.moveTo(0, height/2); //根据progress计算k k=height*(1-progress/100)-A; //振幅A随着progress增大而减小 A=(float) (8*(1-0.5*progress/100)); //绘制完整的一条正弦曲线 for (int i = 0; i < width; i++) { y=(float) (k+A*Math.sin(i*w+fai*w)); mPath.quadTo(i, y, i+1, y); } //把float型转换为字符串并且去掉小数 String textString=String.valueOf(Math.round(progress*100)/100)+" %"; //测量文字宽度,宽度 float textwidth= mPaint.measureText(textString); float textheight=mPaint.descent()-mPaint.ascent(); //绘制文字,使他在波浪下面并且居中 canvas.drawText(textString, (width-textwidth)/2, k+A+textheight, mPaint); mPath.lineTo(width, height); mPath.lineTo(0, height); mPath.close(); canvas.drawPath(mPath, mPaint); //如果进度小于100,则不停的刷新页面,使他动起来 if (progress<100) { fai=fai+10; postInvalidateDelayed(30); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // TODO Auto-generated method stub super.onSizeChanged(w, h, oldw, oldh); width=w; height=h; k=height; } /** * 设置progress进度,更新View,可在子线程中使用 * @param progress */ public void setProgress(float progress) { this.progress=progress; } public float getProgress() { return progress; } }
ok,抛砖引玉,如果大家有更好的实现方式,欢迎分享呀~
^_^