手把手教你画一个 逼格满满圆形水波纹loadingview Android

来源:互联网 发布:黑白网络网址 编辑:程序博客网 时间:2024/05/29 04:15

才没有完结呢o( ̄︶ ̄)n 。大家好,这里是番外篇。

拜读了爱哥的博客,又学到不少东西。爱哥曾经说过: 要站在巨人的丁丁上。 那么今天,我们就站在爱哥的丁丁上来学习制作一款自定义view(开个玩笑,爱哥看到别打我)。


转载请注明出处:http://blog.csdn.net/wingichoy/article/details/50523713

上一篇 带领大家做了一款炫酷的loading动画view 手把手带你做一个超炫酷loading成功动画view  不知道大家跟着做了一遍没有呢?


在开始之前,首先来说说预备知识,这些知识在爱哥的博客上都有详细的介绍:点我进入爱哥自定义view系列

效果图如下:  应用场景很多。。比如。。。内存占用百分比之类的



预备的知识有:

1.贝塞尔曲线    如果你不了解,可以来这里进行基础知识储备:神奇的贝塞尔曲线 

2.Paint.setXfermode()  以及PorterDuffXfermode


千万不要被这个b的名字吓到,不熟悉看到可能会认为很难记,其实 只要站在巨人的丁丁上 还是很简单的。

好了 废话不多说 ,跟我一步步来做一个炫酷的view吧。


首先给一些属性,在构造器里初始化(不要再ondraw new东西不要再ondraw new东西不要再ondraw new东西不要再ondraw new东西

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.     //绘制波纹  
  2.     private Paint mWavePaint;  
  3.   
  4.   
  5.       
  6.   
  7.     private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.XOR);//设置mode 为XOR  
  8.     //绘制圆  
  9.     private Paint mCirclePaint;  
  10.     private Canvas mCanvas;//我们自己的画布  
  11.     private Bitmap mBitmap;  
  12.     private int mWidth;  
  13.     private int mHeight;  
  14.   
  15.     public WaveLoadingView(Context context) {  
  16.         this(context,null);  
  17.     }  
  18.   
  19.     public WaveLoadingView(Context context, AttributeSet attrs) {  
  20.         this(context, attrs,0);  
  21.     }  
  22.   
  23.     public WaveLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {  
  24.         super(context, attrs, defStyleAttr);  
  25.   
  26.         mWavePaint = new Paint();  
  27.         mWavePaint.setColor(Color.parseColor("#33b5e5"));  
  28.         mCirclePaint = new Paint();  
  29.         mCirclePaint.setColor(Color.parseColor("#99cc00"));  
  30.           
  31.   
  32.     }  
  33.     @Override  
  34.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  35.         int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  36.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
  37.         int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
  38.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
  39.         if (widthMode == MeasureSpec.EXACTLY) {  
  40.             mWidth = widthSize;  
  41.         }  
  42.   
  43.   
  44.         if (heightMode == MeasureSpec.EXACTLY) {  
  45.             mHeight = heightSize;  
  46.         }  
  47.         setMeasuredDimension(mWidth, mHeight);  
  48.         mBitmap = Bitmap.createBitmap(300,300, Bitmap.Config.ARGB_8888); //生成一个bitmap  
  49.         mCanvas = new Canvas(mBitmap);//讲bitmp放在我们自己的画布上,实际上mCanvas.draw的时候 改变的是这个bitmap对象  
  50.     }  
  51.       

然后,我们给他绘制一点东西,用来介绍PorterDuffXfermode

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. @Override  
  2.     protected void onDraw(Canvas canvas) {  
  3.         mCanvas.drawCircle(100,100,50,mCirclePaint);  
  4.   
  5.         mCanvas.drawRect(100,100,200,200,mWavePaint);  
  6.         canvas.drawBitmap(mBitmap,0,0,null);  
  7.         super.onDraw(canvas);  
  8.     }  

嗯,可以看到 是我们现在自己的画布上铺了一个bitmap(这里可以理解canvas为桌子  bitmap为画纸,我们在bimap上画画), 然后在bitmap上画了 一个圆,和一个矩形。最后把我们的mBitmap画到系统的画布上(显示到屏幕上),得到了以下效果。


然后我们用setXfermode()方法给他设置一个mode,这里设置XOR。


可以发现! 相交的地方消失了! 是不是很神奇。

在改一个mode 试试

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);  


可以看到 圆形跑到了矩形上面来。  然后巨人给我们总结各个模式如了下图,这里给一个说明dst为先画的 src为后画的:.


大家可以根据这个规律试一下。


现在,我们把圆和矩形重叠。模式去掉。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. protected void onDraw(Canvas canvas) {  
  2.   
  3.        //dst  
  4.        mCanvas.drawCircle(150,150,50,mCirclePaint);  
  5.   
  6. /        mWavePaint.setXfermode(mMode);  
  7.        //src  
  8.        mCanvas.drawRect(100,100,200,200,mWavePaint);  
  9.        canvas.drawBitmap(mBitmap,0,0,null);  
  10.        super.onDraw(canvas);  
  11.    }  

运行是这样的。


日了狗了!!我的圆怎么没了。。  其实圆是被覆盖掉了。 然后我们想实现一个效果,就是在圆的范围内,显示矩形的内容,该怎么做呢。自己照着图找找吧哈哈。


--------------------------------------------回归正题------------------------------------

我们要实现的是一个圆形的水波纹那种loadingview。。首要就是实现这个水波纹。

这时候贝塞尔曲线就派上用场了。这里采用三阶贝塞尔, 不停地改变X 模拟水波效果。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1.  if (x > 50) {  
  2.             isLeft = true;  
  3.         } else if (x < 0) {  
  4.             isLeft = false;  
  5.         }  
  6. <span style="white-space:pre">        </span>if (y > -50) {  //大于-50是因为辅助点是50  为了让他充满整个屏幕  
  7.             y--;  
  8.         }        if (isLeft) {  
  9.             x = x - 1;  
  10.         } else {  
  11.             x = x + 1;  
  12.         }  
  13.         mPath.reset();  
  14.         mPath.moveTo(0,  y);  
  15.         mPath.cubicTo(100 + x*250 + y, 100 + x*2, y-50, mWidth, y);//前两个参数是辅助点  
  16.         mPath.lineTo(mWidth, mHeight);//充满整个画布  
  17.         mPath.lineTo(0, mHeight);//充满整个画布  
  18.         mPath.close();  

之后用mCanvas来绘制这个bitmap,要注意的是 绘制之前要清空mBitmap,不然path会重叠

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. mBitmap.eraseColor(Color.parseColor("#00000000"));  
  2.   
  3. //dst  
  4.  mCanvas.drawPath(mPath, mPaint);  

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. canvas.drawBitmap(mBitmap, 00null);  
  2.   
  3.   
  4.        postInvalidateDelayed(10);  
在最上面动态改变Y  通知重绘,现在的效果是这样的


 哈,水波效果出来了。   接着想办法让他画到一个圆形中。 首先绘制一个圆

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mSRCPaint);  


额。。有点海上日出的感觉(看太阳都是绿色!)

现在让我们回到刚才的问题,如何在dst的范围内绘制src呢。。。答案是。。SRC_IN 你找对了吗。添加模式

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. //dst  
  2.       mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mSRCPaint);  
  3.   
  4.       mPaint.setXfermode(mMode);  
  5.       //src  
  6.       mCanvas.drawPath(mPath, mPaint);  
  7.   
  8.       canvas.drawBitmap(mBitmap, 00null);  

运行 效果如下:


咦 哈哈哈,是不是有点感觉了。如果不这样做 就需要考虑好多问题。动态计算沿着圆弧x,y坐标  计算arcTo的范围(我已经算出来了。。有兴趣的可以提。。没兴趣的话我就不写了。。)


完善一下,添加一个percent来代表进度,让y来根据percent动态改变

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. y = (int) ((1-mPercent /100f) *mHeight);  


添加setPercent方法

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public void setPercent(int percent){  
  2.         mPercent = percent;  
  3.     }  


画上百分比的文字。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. String str = mPercent + "%";  
  2.        float txtLength = mTextPaint.measureText(str);  
  3.        canvas.drawText(mPercent + "%", mWidth / 2-txtLength/2, mHeight / 2, mTextPaint);  

然后配合seekBar。 效果如下:





最后改改字体大小  画笔透明度。 添加个背景图 就成了效果图上的效果。

0 0
原创粉丝点击