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

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

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

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

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

本项目地址:点击打开链接

预备的知识有:

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

2.Paint.setXfermode()  以及PorterDuffXfermode

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

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

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

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

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

  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 试试

  1. private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);

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

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

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

  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 模拟水波效果。

  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*2, 50 + 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会重叠

  1. mBitmap.eraseColor(Color.parseColor("#00000000"));
  2.  
  3. //dst
  4.  mCanvas.drawPath(mPath, mPaint);

  1. canvas.drawBitmap(mBitmap, 0, 0, null);
  2.  
  3. postInvalidateDelayed(10);

在最上面动态改变Y  通知重绘,现在的效果是这样的

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

  1. mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mSRCPaint);

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

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

  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, 0, 0, null);

运行 效果如下:

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

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

  1. y = (int) ((1-mPercent /100f) *mHeight);

添加setPercent方法

  1. public void setPercent(int percent){
  2. mPercent = percent;
  3. }

画上百分比的文字。

  1. String str = mPercent + "%";
  2. float txtLength = mTextPaint.measureText(str);
  3. canvas.drawText(mPercent + "%", mWidth / 2-txtLength/2, mHeight / 2, mTextPaint);

然后配合seekBar。 效果如下:

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

如果你觉得本博客还可以,那么求关注,点个顶,评个论咯。。以后还会有更多的文章等着你~

手把手教你画一个 逼格满满圆形水波纹loadingview Android的更多相关文章

  1. 只有20行Javascript代码!手把手教你写一个页面模板引擎

    http://www.toobug.net/article/how_to_design_front_end_template_engine.html http://barretlee.com/webs ...

  2. iOS回顾笔记(05) -- 手把手教你封装一个广告轮播图框架

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  3. PWA入门:手把手教你制作一个PWA应用

    摘要: PWA图文教程 原文:PWA入门:手把手教你制作一个PWA应用 作者:MudOnTire Fundebug经授权转载,版权归原作者所有. 简介 Web前端的同学是否想过学习app开发,以弥补自 ...

  4. R数据分析:跟随top期刊手把手教你做一个临床预测模型

    临床预测模型也是大家比较感兴趣的,今天就带着大家看一篇临床预测模型的文章,并且用一个例子给大家过一遍做法. 这篇文章来自护理领域顶级期刊的文章,文章名在下面 Ballesta-Castillejos ...

  5. 手把手带你画一个动态错误提示 Android自定义view

    嗯..再差1篇就可以获得持之以恒徽章了,今天带大家画一个比较简单的view. 转载请注明出处:http://blog.csdn.net/wingichoy/article/details/504771 ...

  6. 用Python手把手教你搭一个Transformer!

    来源商业新知网,原标题:百闻不如一码!手把手教你用Python搭一个Transformer 与基于RNN的方法相比,Transformer 不需要循环,主要是由Attention 机制组成,因而可以充 ...

  7. 手把手教你画AndroidK线分时图及指标

    先废话一下:来到公司之前.项目是由外包公司做的,面试初,没有接触过分时图k线这块,认为好难,我能搞定不.可是一段时间之后,发现之前做的那是一片稀烂,可是这货是主功能啊.迟早的自己操刀,痛下决心,开搞, ...

  8. 手把手带你画一个漂亮蜂窝view Android自定义view

    上一篇做了一个水波纹view  不知道大家有没有动手试试呢点击打开链接 这个效果做起来好像没什么意义,如果不加监听回调 图片就能直接替代.写这篇博客的目的是锻炼一下思维能力,以更好的面多各种自定义vi ...

  9. 手把手教你打造一个纯CSS图标库

    来,干了这碗安利 写这篇文章的目的其实就是为了安利一下我的图标库:iconoo,所以,开门见山,star吧少年少妇们!(这样的我是不是应该要加个github互粉的团伙了?) 主题说完了,下面进入正题. ...

随机推荐

  1. Go 语言函数

    函数是基本的代码块,用于执行一个任务. Go 语言最少有个 main() 函数. 你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务. 函数声明告诉了编译器函数的名称,返回类型,和参数. ...

  2. jQuery 遍历 – 祖先

    祖先是父.祖父或曾祖父等等. 通过 jQuery,您能够向上遍历 DOM 树,以查找元素的祖先. 向上遍历 DOM 树 这些 jQuery 方法很有用,它们用于向上遍历 DOM 树: parent() ...

  3. Docker学习笔记2: Docker 概述

    一.什么是Docker Docker是基于Go语言实现的云开源项目. Docker 的主要目标是:"Bulid,Ship and  Run Any App ,AnyWhere" , ...

  4. Matlab to OpenCV Mat

    convert Matlab matrix to OpenCV Mat. Support CV_32FC3 only currently. The Code int matlab2opencv(cv: ...

  5. 给定一数组,输出满足2a=b(a,b代表数组中的数)的数对,要求时间复杂度尽量低。

    //时间复杂度O(n),空间复杂度O(n) void findSequence(int* arr, int len) { int* hashtable = new int[RANGE]; memset ...

  6. Spark-1.6.0之Application运行信息记录器JobProgressListener

    JobProgressListener类是Spark的ListenerBus中一个很重要的监听器,可以用于记录Spark任务的Job和Stage等信息,比如在Spark UI页面上Job和Stage运 ...

  7. Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52629449 前言:上篇文中分析 ...

  8. scala学习笔记3(trait)

    // trait 类似于 Java8 中可以带 default method 的接口. // trait 中可以带有实现的方法,也可以带有抽象的方法,使用 trait 的方式是 with 而混入类中 ...

  9. Error running app: Instant Run requires 'Tools | Android | Enable ADB integration' to be enabled.

    废了半天劲才解决... 就三步:菜单栏,Tools -> Adnroid -> enable ADB integration

  10. path和classpath的区别

    path的作用 path是系统用来指定可执行文件的完整路径,即使不在path中设置JDK的路径也可执行JAVA文件,但必须把完整的路径写出来,如C:\Program Files\Java\jdk1.6 ...