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都在上面的地址中,如果有什么问题可以给我留言,谢谢!

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

(0)

相关推荐

  • 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项目实战手把手教你画圆形水波纹loadingview

    本文实例讲解的是如何画一个满满圆形水波纹loadingview,这类效果应用场景很多,比如内存占用百分比之类的,分享给大家供大家参考,具体内容如下 效果图如下: 预备的知识: 1.贝塞尔曲线    如果你不了解,可以来这里进行基础知识储备:神奇的贝塞尔曲线 2.Paint.setXfermode()  以及PorterDuffXfermode 千万不要被这个b的名字吓到,不熟悉看到可能会认为很难记,其实 只要站在巨人的丁丁上 还是很简单的. 好了 废话不多说 ,跟我一步步来做一个炫酷的view吧

  • Android仿水波纹流量球进度条控制器

    仿水波纹流球进度条控制器,Android实现高端大气的主流特效,供大家参考,具体内容如下 效果图: CircleView 这里主要是实现中心圆以及水波特效 package com.lgl.circleview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.gra

  • Android实现兼容的水波纹效果

    先看看效果图 其实,要实现这一效果很简单,只要分drawable和drawablev21两个文件夹就好了. 普通情况下的selector: <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@c

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

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

  • Android实现水波纹效果

    一.效果 点击开始: 点击停止: 二.在MainActivity中 import android.graphics.Paint; import android.os.Bundle; import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.support.v7.app.AppCompatActivity; import android.view.View; import android

  • Android 自定义view实现水波纹动画效果

    在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当然就是希望你能给她: 在这样的关键时候,身子板就一定得硬了,可千万别说不行,爷们儿怎么能说不行呢: 好了,为了让大家都能给妹纸们想要的,后面会逐渐分享一些比较比较不错的效果,目的只有一个,通过自定义view实现我们所能实现的动效: 今天主要分享水波纹效果: 1.标准正余弦水波纹: 2.非标准圆形液柱水波纹: 虽说都是水波纹,但两者在实现上差异是比较大的,一个

  • Android实现点击Button产生水波纹效果

    先上图,看看接下来我要向大家介绍的是个什么东西,如下图: 接下来要介绍的就是如何实现上述图中的波纹效果,这种效果如果大家没有体验过的话,可以看看百度手机卫士或者360手机卫士,里面的按钮点击效果都是这样的,另外Android 5.0以上的版本也出现了这种效果.不多说,下面聊聊具体的怎么实现. 首先大家看到的是三个button,水波纹的出现给我们的错觉是直接将波纹绘制在button上面的,但是这样能做到吗?首先button自己有background和src,如果把半透明的水波纹当作backgrou

  • Android实现自定义华丽的水波纹效果

    先来看看效果 实现效果 模拟水波纹的效果:点击屏幕就有圆环出现,半径从小到大,透明度从大到小(0为透明) 实现思路 1.自定义类继承View. 2.定义每个圆环的实体类 Wave,并初始化绘制圆环的画笔的数据. 3.重写onTouchEvent方法,down时,获得坐标点,做为圆环圆心. 4.发送handler信息,对数据进行修改,刷新页面. 5.重写onDraw方法,绘制一个圆环. 1. 自定义类继承View 新建WaterWaveView2类继承View public class Water

  • Android特效之水波纹的实现

    前言 水波纹特效,想必大家或多或少见过,在我的印象中,大致有如下几种: 支付宝 "咻咻咻" 式 流量球 "荡漾" 式 真实的水波纹效果,基于Bitmap处理式 话不多说,先来看看效果: 填充式水波纹,间距相等 非填充式水波纹,间距相等 非填充式水波纹,间距不断变大 填充式水波纹,间距不断变小 想必大家已经知道基本的原理了,就是用Canvas来画嘛,但可不是简单的画哦,请往下看. 分析 这种类型的水波纹,其实无非就是画圆而已,在给定的矩形中,一个个圆由最小半径扩大到最

随机推荐