先看效果图:
你可以定义成你项目的logo图片,可以设置水波颜色、波长、波宽、字体大小、颜色、进度条的最大值,当前进度值,还可以设置波纹震动的快慢。当设置一个进度不变的时候,打开时还有一个动画填满的效果(比如第二个流量显示,这里图片没有截出这个效果)。
源码地址
1. 如何使用
1.1 在布局文件中
添加自定义控件:
<cn.fanrunqi.waveprogressvIEw.WaveProgressVIEw androID:ID="@+ID/waveProgressbar" androID:background="@drawable/circle" <!--androID:background="@drawable/bg_a"--> androID:layout_wIDth="130dp" androID:layout_height="130dp" />
说明,这里的androID:background定义的是控件的形状,比如上面的圆形和美女,你可用shape.xml定义形状图片。
比如,这是一个圆
<?xml version="1.0" enCoding="utf-8"?><shape xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:shape="oval"> <solID androID:color="#ddddDD"/> <size androID:wIDth="150dp" androID:height="150dp"/></shape>
也可以直接给androID:background设置一张图片,比如:
这里注意透明像素,还有为了图片缩放的时候不变形,建议背景(不管是图片还是图形)为正方形。
1.2 在代码中
你可以选择进行如下设置:
//设置当前进度值和当前显示的文字waveProgressbar.setCurrent(int currentProgress,String currentText); // 77,"788M/1024M"//设置进度条的最大值waveProgressbar.setMaxProgress(int maxProgress);//设置显示文字的大小和颜色waveProgressbar.setText(String mTextcolor,int mTextSize);//"#FFFF00",41//设置水波的颜色waveProgressbar.setWavecolor(String mWavecolor); //"#5b9ef4"//设置波浪的高度和波浪的宽度(均为一个波峰的大小)waveProgressbar.setWave(float mWaveHight,float mWaveWIDth);//设置波浪的上下震动的速度(这里注意值越大,震动的越小)waveProgressbar.setmWaveSpeed(int mWaveSpeed);//The larger the value,the slower the vibration
2. 代码实现
这里实现主要用到的知识有 自定义view、PorterDuffXfermode和二阶贝塞尔曲线,不太清楚的可以在我博客找找,都有的。
首先自定义WaveProgressVIEw继承VIEw,在构造函数中获取布局文件中设置的背景,同时设置一个画波浪的画笔和画文字的画笔。
private voID Init() { /** * 获得背景 */ if(null==getBackground()){ throw new IllegalArgumentException(String.format("background is null.")); }else{ backgroundBitmap = getBitmapFromDrawable(getBackground()); } /** * 波浪画笔 */ mPath = new Path(); mPathPaint = new Paint(); mPathPaint.setAntiAlias(true); mPathPaint.setStyle(Paint.Style.FILL); /** * 进度画笔 */ mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextAlign(Paint.Align.CENTER); //开始不断自我绘制,让波浪动起来 handler.sendEmptyMessageDelayed(INVALIDATE,100); }
复写onDraw方法,先把波浪画在画布上,然后画背景(给背景画笔设置PorterDuff.Mode.DST_Atop模式:取上层非交集部分与下层交集部分 )。当然也可以是PorterDuff.Mode.SRC_Atop,主要取决于你画的先后顺序。最后把文字画上去,形成一个最终Bitmap,最后把这个Bitmap画到onDraw的参数canvas上。
Paint paint = new Paint(); paint.setAntiAlias(true); Bitmap finalBmp = Bitmap.createBitmap(wIDth,height,Bitmap.Config.ARGB_8888); /** * 产生一个同样大小的画布 */ Canvas canvas = new Canvas(finalBmp); /** * 绘制波浪 */ float CurMIDY = height*(maxProgress-currentProgress)/maxProgress; if(CurY>CurMIDY){ CurY = CurY - (CurY-CurMIDY)/10; } mPath.reset(); mPath.moveto(0-distance,CurY); int waveNum = wIDth/((int)mWaveHalfWIDth*4)+1; int multiplIEr = 0; for(int i =0;i<waveNum;i++){ mPath.quadTo(mWaveHalfWIDth*(multiplIEr+1)-distance,CurY-mWaveHight,mWaveHalfWIDth*(multiplIEr+2)-distance,CurY); mPath.quadTo(mWaveHalfWIDth*(multiplIEr+3)-distance,CurY+mWaveHight,mWaveHalfWIDth*(multiplIEr+4)-distance,CurY); multiplIEr+=4; } distance +=mWaveHalfWIDth/mWaveSpeed; distance = distance%(mWaveHalfWIDth*4); mPath.lineto(wIDth,height); mPath.lineto(0,height); mPath.close(); canvas.drawPath(mPath,mPathPaint); /** * 对图片给进行缩放 */ int min = Math.min(wIDth,height); backgroundBitmap = Bitmap.createScaledBitmap(backgroundBitmap,min,false); /** * 使用DST_Atop,取上层非交集部分与下层交集部分 。 */ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_Atop)); /** * 绘制图片 */ canvas.drawBitmap(backgroundBitmap,paint); /** * 绘制进度文字 */ canvas.drawText(currentText,wIDth/2,height/2,mTextPaint); return finalBmp;
这里的CurY是上次波浪中线的y轴坐标,CurMIDY 是当前的Y轴坐标,每次波浪上升的时候为了不产生卡顿效果,把这1/100的上升分为10次来绘制。
distance是x轴的偏移量,为了使水波动起来,每次绘制时都要向左进行一段偏移。
distance +=mWaveHalfWIDth/mWaveSpeed;distance = distance%(mWaveHalfWIDth*4);
每次偏移距离为 半波宽度/波浪震动速度,因为一个波是4个半波宽度形成一个循环,然后又回到最开始x位置开始循环位移。
根据vIEw的宽度计算出一共要绘制多少个波形出来,同时多加一个波为了向左平移。
int waveNum = wIDth/((int)mWaveHalfWIDth*4)+1; int multiplIEr = 0; for(int i =0;i<waveNum;i++){ mPath.quadTo(mWaveHalfWIDth*(multiplIEr+1)-distance,CurY); mPath.quadTo(mWaveHalfWIDth*(multiplIEr+3)-distance,CurY); multiplIEr+=4; }
每次绘制以波形的左边点、波形的右边点、vIEw的左下角、vIEw的右下角、形成一个图片把它绘制到内存中新建的和vIEw同大小的canvas上。
mPath.reset();mPath.moveto(0-distance,CurY);mPath.lineto(wIDth,height);mPath.lineto(0,height);mPath.close();canvas.drawPath(mPath,mPathPaint);
先对背景图形进行缩放再绘制到canvas上,这里的缩放是按最小边进行缩放。
int min = Math.min(wIDth,height);backgroundBitmap = Bitmap.createScaledBitmap(backgroundBitmap,false);
最后把文字绘制上去,注意我们在初始化中设置了画笔,为了能通过代码设置文字的颜色,要把设置文字画笔颜色和大小放在onDraw方法中。
mPathPaint.setcolor(color.parsecolor(mWavecolor));mTextPaint.setcolor(color.parsecolor(mTextcolor));mTextPaint.setTextSize(mTextSize);canvas.drawText(currentText,mTextPaint);
为了使波浪动起来,使用handler循环调用invalIDate刷新界面。同时应该在构造函数打开handler循环。
private static final int INVALIDATE = 0X777; private Handler handler = new Handler() { @OverrIDe public voID handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case INVALIDATE: invalIDate(); sendEmptyMessageDelayed(INVALIDATE,RefreshGap); break; } } };
最后就是一些相关属性设置的函数。
/** * @param currentProgress 当前进度 * @param currentText 当前显示的进度文字 */ public voID setCurrent(int currentProgress,String currentText) { this.currentProgress = currentProgress; this.currentText = currentText; } /** * @param maxProgress 设置进度条的最大值,默认100 */ public voID setMaxProgress(int maxProgress){ this.maxProgress = maxProgress; } /** * @param mTextcolor 文字的颜色 * @param mTextSize 文字的大小 */ public voID setText(String mTextcolor,int mTextSize){ this.mTextcolor = mTextcolor; this.mTextSize = mTextSize; } /** * @param mWaveHight 波峰的高度 * @param mWaveWIDth 一个波峰的宽度 */ public voID setWave(float mWaveHight,float mWaveWIDth){ this.mWaveHight = mWaveHight; this.mWaveHalfWIDth = mWaveWIDth/2; } /** * @param mWavecolor 水的颜色 */ public voID setWavecolor(String mWavecolor){ this.mWavecolor = mWavecolor; } /** * 值越大震荡的越慢 * @param mWaveSpeed */ public voID setmWaveSpeed(int mWaveSpeed){ this.mWaveSpeed = mWaveSpeed; }
实现还是比较简单的,源码和demo都在上面的地址中,如果有什么问题可以给我留言,谢谢!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。
以上是内存溢出为你收集整理的Android自定义WaveProgressView实现水波纹加载需求全部内容,希望文章能够帮你解决Android自定义WaveProgressView实现水波纹加载需求所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)