Android自定义WaveProgressView实现水波纹加载需求

先看效果图:

  你可以定义成你项目的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,min,false); /** * 使用DST_ATOP,取上层非交集部分与下层交集部分 。 */ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP)); /** * 绘制图片 */ canvas.drawBitmap(backgroundBitmap,0,0,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-mWaveHight,mWaveHalfWidth*(multiplier+2)-distance,CurY); mPath.quadTo(mWaveHalfWidth*(multiplier+3)-distance,CurY+mWaveHight,mWaveHalfWidth*(multiplier+4)-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,min,min,false);

最后把文字绘制上去,注意我们在初始化中设置了画笔,为了能通过代码设置文字的颜色,要把设置文字画笔颜色和大小放在onDraw方法中。

mPathPaint.setColor(Color.parseColor(mWaveColor)); mTextPaint.setColor(Color.parseColor(mTextColor)); mTextPaint.setTextSize(mTextSize); canvas.drawText(currentText, width/2, height/2, 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都在上面的地址中,如果有什么问题可以给我留言,谢谢!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-09-25 01:39:32

Android自定义WaveProgressView实现水波纹加载需求的相关文章

Android自定义view实现阻尼效果的加载动画_Android

效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

Android自定义View实现loading动画加载效果

项目开发中对Loading的处理是比较常见的,安卓系统提供的不太美观,引入第三发又太麻烦,这时候自己定义View来实现这个效果,并且进行封装抽取给项目提供统一的loading样式是最好的解决方式了. 先自定义一个View,继承自LinearLayout,在Layout中,添加布局控件 /** * Created by xiedong on 2017/3/7. */ public class Loading_view extends LinearLayout { private Context m

Android自定义View 实现水波纹动画引导效果

一.实现效果图 二.实现代码 1.自定义view package com.czhappy.showintroduce.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Pat

Android自定义view实现阻尼效果的加载动画

效果: 需要知识: 1. 二次贝塞尔曲线 2. 动画知识 3. 基础自定义view知识 先来解释下什么叫阻尼运动 阻尼振动是指,由于振动系统受到摩擦和介质阻力或其他能耗而使振幅随时间逐渐衰减的振动,又称减幅振动.衰减振动.[1] 不论是弹簧振子还是单摆由于外界的摩擦和介质阻力总是存在,在振动过程中要不断克服外界阻力做功,消耗能量,振幅就会逐渐减小,经过一段时间,振动就会完全停下来.这种振幅随时间减小的振动称为阻尼振动.因为振幅与振动的能量有关,阻尼振动也就是能量不断减少的振动.阻尼振动是非简谐运

Android 自定义圆形头像CircleImageView支持加载网络图片的实现代码

在Android开发中我们常常用到圆形的头像,如果每次加载之后再进行圆形裁剪特别麻烦.所以在这里写一个自定义圆形ImageView,直接去加载网络图片,这样的话就特别的方便. 先上效果图 主要的方法 1.让自定义 CircleImageView 继承ImageView /** * 自定义圆形头像 * Created by Dylan on 2015/11/26 0026. */ public class CircleImageView extends ImageView { } 2.在构造方法中

Android 自定义view实现进度条加载效果实例代码

这个其实很简单,思路是这样的,就是拿view的宽度,除以点的点的宽度+二个点 之间的间距,就可以算出大概能画出几个点出来,然后就通过canvas画出点,再然后就是每隔多少时间把上面移动的点不断的去改变它的坐标就可以, 效果如下: 分析图: 代码如下: package com.example.dotloadview; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bit

Android自定义view实现水波纹进度球效果_Android

今天我们要实现的这个view没有太多交互性的view,所以就继承view. 自定义view的套路,套路很深       1.获取我们自定义属性attrs(可省略)       2.重写onMeasure方法,计算控件的宽和高       3.重写onDraw方法,绘制我们的控件 这么看来,自定义view的套路很清晰嘛. 我们看下今天的效果图,其中一个是放慢的效果(时间调的长) 我们按照套路来. 一.自定义属性 <declare-styleable name="WaveProgressVie

Android自定义标题栏:显示网页加载进度

 这阵子在做Lephone的适配,测试组提交一个bug:标题栏的文字较长时没有显示完全,其实这并不能算个bug,并且这个问题在以前其他机器也没有出现,只是说在Lephone的这个平台上显示得不怎么美观,因为联想将原生的标题栏UI进行了修改.修改的过程中遇到了一个难题,系统自带的那个标题栏进度总能够到达100%后渐退,但是我每次最后到100%那一段显示不全,尝试了用线程程序死了卡主了不说,还是一样的效果,后来同事一句话提醒了我用动画.确实是这样我猜系统的也是这样实现的,等进度到达100%后,用动画

Android自定义Dialog实现文字动态加载效果_Android

之前在技术问答上面看到一个提问 "加载中-" 后面三个点是动态的,这么一个效果实现.想来想去,好像没想到好的处理方式. 尝试了一下,以一个最笨的方式实现了.先来看一下效果 : 我是通过自定义一个Dialog,加载中的效果,是在Dialog内部实现的,进度还是从Activity里面控制的. 下面是Dialog实现类: public class CustomDialog extends AlertDialog { public CustomDialog(Context context) {