Android项目实战手把手教你画圆形水波纹loadingview

本文实例讲解的是如何画一个满满圆形水波纹loadingview,这类效果应用场景很多,比如内存占用百分比之类的,分享给大家供大家参考,具体内容如下
效果图如下:

预备的知识:

  • 1.贝塞尔曲线    如果你不了解,可以来这里进行基础知识储备:神奇的贝塞尔曲线
  • 2.Paint.setXfermode()  以及PorterDuffXfermode

千万不要被这个b的名字吓到,不熟悉看到可能会认为很难记,其实 只要站在巨人的丁丁上 还是很简单的。
好了 废话不多说 ,跟我一步步来做一个炫酷的view吧。

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

  //绘制波纹
  private Paint mWavePaint;
  private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.XOR);//设置mode 为XOR
  //绘制圆
  private Paint mCirclePaint;
  private Canvas mCanvas;//我们自己的画布
  private Bitmap mBitmap;
  private int mWidth;
  private int mHeight; 

  public WaveLoadingView(Context context) {
    this(context,null);
  } 

  public WaveLoadingView(Context context, AttributeSet attrs) {
    this(context, attrs,0);
  } 

  public WaveLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr); 

    mWavePaint = new Paint();
    mWavePaint.setColor(Color.parseColor("#33b5e5"));
    mCirclePaint = new Paint();
    mCirclePaint.setColor(Color.parseColor("#99cc00")); 

  }
  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    if (widthMode == MeasureSpec.EXACTLY) {
      mWidth = widthSize;
    } 

    if (heightMode == MeasureSpec.EXACTLY) {
      mHeight = heightSize;
    }
    setMeasuredDimension(mWidth, mHeight);
    mBitmap = Bitmap.createBitmap(300,300, Bitmap.Config.ARGB_8888); //生成一个bitmap
    mCanvas = new Canvas(mBitmap);//讲bitmp放在我们自己的画布上,实际上mCanvas.draw的时候 改变的是这个bitmap对象
  }

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

@Override
  protected void onDraw(Canvas canvas) {
    mCanvas.drawCircle(100,100,50,mCirclePaint); 

    mCanvas.drawRect(100,100,200,200,mWavePaint);
    canvas.drawBitmap(mBitmap,0,0,null);
    super.onDraw(canvas);
  } 

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

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

可以发现! 相交的地方消失了! 是不是很神奇。
在改一个mode 试试

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

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

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

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

protected void onDraw(Canvas canvas) { 

    //dst
    mCanvas.drawCircle(150,150,50,mCirclePaint); 

/    mWavePaint.setXfermode(mMode);
    //src
    mCanvas.drawRect(100,100,200,200,mWavePaint);
    canvas.drawBitmap(mBitmap,0,0,null);
    super.onDraw(canvas);
  }

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

我们要实现的是一个圆形的水波纹那种loadingview。。首要就是实现这个水波纹。
这时候贝塞尔曲线就派上用场了。这里采用三阶贝塞尔, 不停地改变X 模拟水波效果。

 if (x > 50) {
      isLeft = true;
    } else if (x < 0) {
      isLeft = false;
    }
<span style="white-space:pre">    </span>if (y > -50) { //大于-50是因为辅助点是50 为了让他充满整个屏幕
      y--;
    }    if (isLeft) {
      x = x - 1;
    } else {
      x = x + 1;
    }
    mPath.reset();
    mPath.moveTo(0, y);
    mPath.cubicTo(100 + x*2, 50 + y, 100 + x*2, y-50, mWidth, y);//前两个参数是辅助点
    mPath.lineTo(mWidth, mHeight);//充满整个画布
    mPath.lineTo(0, mHeight);//充满整个画布
    mPath.close();

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

mBitmap.eraseColor(Color.parseColor("#00000000")); 

//dst
 mCanvas.drawPath(mPath, mPaint); 

canvas.drawBitmap(mBitmap, 0, 0, null); 

    postInvalidateDelayed(10);

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

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

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

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

   mPaint.setXfermode(mMode);
   //src
   mCanvas.drawPath(mPath, mPaint); 

   canvas.drawBitmap(mBitmap, 0, 0, null); 

是不是有点感觉了。如果不这样做 就需要考虑好多问题。动态计算沿着圆弧x,y坐标  计算arcTo的范围。

完善一下,添加一个percent来代表进度,让y来根据percent动态改变
y = (int) ((1-mPercent /100f) *mHeight);

添加setPercent方法

public void setPercent(int percent){
    mPercent = percent;
  } 

画上百分比的文字。

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

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

是不是很有趣,大家可以动手实现一下!

(0)

相关推荐

  • Android自定义View画圆功能

    本文实例为大家分享了Android自定义View画圆的具体代码,供大家参考,具体内容如下 引入布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools&q

  • Android自定view画圆效果

    这是一个自定义view画圆,对于初学自定义view的小伙伴这是一个很好的帮助. 看图 代码: package sjx.com.custonview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.support.annotation.Nullable; impor

  • Android项目实战手把手教你画圆形水波纹loadingview

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

  • Android 项目实战之头像选择功能

    一.图片选择 1.1 目标 1.实现如图所示功能:能够出现相册和相机选项 2.能够对选择的图片进行裁剪 1.2 功能实现 1.2.1 Intent工具类封装 封装图片选择和图片裁剪的工具类 /** * 选择图片(从相册或相机) * @param uri 相机存储uri * @return */ public static Intent getPhotoSelectIntent(Uri uri){ Intent take = new Intent(MediaStore.ACTION_IMAGE_C

  • Android项目实战之Glide 高斯模糊效果的实例代码

    核心需要高斯模糊的库 compile 'jp.wasabeef:glide-transformations:2.0.1' 针对于3.7的版本 使用方法为: //加载背景, Glide.with(MusicPlayerActivity.this) .load(service.getImageUri()) .dontAnimate() .error(R.drawable.no_music_rotate_img) // 设置高斯模糊,模糊程度(最大25) 缩放比例 .bitmapTransform(n

  • Android项目实战之百度地图地点签到功能

    前言:先写个简单的地点签到功能,如果日后有时间细写的话,会更加好好研究一下百度地图api,做更多逻辑判断. 这里主要是调用百度地图中的场景定位中的签到场景.通过官方文档进行api集成.通过GPS的定位功能,获取地理位置,时间,用户名进行存储.之后通过日历显示历史签到记录. 效果图: /**百度地图sdk**/ implementation files('libs/BaiduLBS_Android.jar') /**日历选择器**/ implementation 'com.prolificinte

  • Android项目实战之ListView悬浮头部展现效果实现

    目录 实现效果: 我们先分析要解决的问题: 解决: 代码实现: 总结 实现效果: 先看下效果:需求是 滑动列表 ,其中一部分视图(粉丝数,关注数这一部分)在滑动到顶端的时候不消失,而是停留在整个界面头部. 我们先分析要解决的问题: 1.如何实现列表ListView顶部视图跟随ListView一起滑动 2.如何实现滑动过程中需要停留在顶部的视图 解决: 第一个问题,实现ListView与顶部视图一起滑动,ListView提供一个方法,addHeadView(View); 意思就是在ListView

  • Android如何自定义View实现横向的双水波纹进度条

    目录 思路分析 功能实现 1.绘制圆角背景和圆角矩形边框 2.通过贝塞尔曲线实现双水波 3.设置动画使进度和水波纹变化 结语 网上垂直的水波纹进度条很多,但横向的很少,将垂直的水波纹改为水平的还遇到了些麻烦,现在完善后发布出来,希望遇到的人少躺点坑. 思路分析 整体效果可分为三个,绘制圆角背景和圆角矩形,绘制第一条和第二条水波浪,根据自定义进度变化效果. 功能实现 1.绘制圆角背景和圆角矩形边框 圆角矩形边框: private RectF rectBorder; if (rectBorder =

  • Android项目实战(二十八):使用Zxing实现二维码及优化实例

    前言: 多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意. 当然,项目中我们也许只会用到二维码的扫描和生成两个功能,所以不必下载完整的jar包,使用简化版的即可,下文可见. 这篇文章讲述: 1.如果快速在项目中集成zxing,实现扫描和生成二维码功能 2.根据项目需求去修改源码实现我们的要求并进行优化 一.快速集成zxing二维码 1.下载库文件 :http://xiazai.jb51.net/201611/yuanma/ZXingB

  • Android项目实战教程之高仿网易云音乐启动页实例代码

    前言 本文主要给大家介绍了关于Android高仿网易云音乐启动页的相关内容,这一节我们来讲解启动界面,效果如下: 首次创建一个SplashActivity用来做启动界面,因为创建完项目默认是MainActivity做主界面,所以需要去掉,将启动配置到同时去掉SplashActivity,并且去掉SplashActivity的标题栏,同时还要设置为全屏. Activity启动配置 在清单文件将启动配置剪贴到SplashActivity: <activity android:name=".ac

  • Android项目实战之仿网易顶部导航栏效果

    随着时间的推移现在的软件要求显示的内容越来越多,所以要在小的屏幕上能够更好的显示更多的内容,首先我们会想到底部菜单栏,但是有时候想网易新闻要显示的内容太多,而且又想在主页面全部显示出来,所以有加了顶部导航栏,但是Android这样的移动设备内存是受限的,那么多界面缓存到内存中,很容易导致内存溢出,这个是比较致命的,所以不得不考虑.虽然我在之前也做过网易的顶部导航栏但是方式并不好,就像使用viewpager做一些复杂的界面由于图片占用内存过多,很容易导致内存溢出,学习了今天的内容大家做一下对比相信

  • Android项目实战之仿网易新闻的页面(RecyclerView )

    本文实例实现一个仿网易新闻的页面,上面是轮播的图片,下面是 RecyclerView 显示新闻列表,具体内容如下 错误方法 <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...> <ViewPager ... /> <android.support.v7.widget.RecyclerView .../> </LinearLayout> 这样布局

随机推荐