Android自定义View之水波纹显示进度效果

        显示进度在我们APP中随处可见,今天我们来撸一撸水波纹进度效果,具体效果请看下图:

                                    

        这是一个自定义View,大家可以明显的看到,自定义View中用到了贝塞尔曲线,我们先来简单了解下贝塞尔曲线。
          贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。贝塞尔曲线是计算机图形学中相当重要的参数曲线,在一些比较成熟的位图软件中也有贝塞尔曲线工具,如PhotoShop等。在Flash4中还没有完整的曲线工具,而在Flash5里面已经提供出贝塞尔曲线工具。(我是百度百科的搬运工)
        我们用到的是二阶贝塞尔曲线,其方程为:
        起始点P0,终点P2,只有一个控制点P1,看起来是这样的:
                                
        但我们并不用自己去写贝塞尔曲线相关的代码,Path类已经给我们做了封装,我们只需调用封装了二阶贝塞尔曲线的quadTo(float x1,float y1,float x2,float y2)方法。
        如果有小伙伴对Path类 不熟的,我推荐一篇博客:Path从懵逼到精通--基本操作
        此自定义View的主要部分就是在onDraw()里面完成的,具体代码如下:
 @Override
    protected void onDraw(Canvas canvas) {

        if (null != backgroundBitmap) {
            canvas.drawBitmap(createImage(), 0, 0, null);
        }
    }

    private Bitmap createImage() {
        mPathPaint.setColor(Color.parseColor(mWaveColor));
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        //剩余进度
        float currentMidY = height * (maxProgress - currentProgress) / maxProgress;
        if (currentY > currentMidY) {//每次增长currentY-currentMidY)/10
            currentY = currentY - (currentY - currentMidY) / 10;
        }
        //清除掉path里的线条和曲线,但是不会改变它的fill-type
        mPath.reset();
        //移动路径的起始点到(0 - distance, currentY)
        mPath.moveTo(0 - distance, currentY);
        //显示的区域内的水波纹的数量
        int waveNum = width / ((int) mWaveWidth);
        int num = 0;
        for (int i = 0; i < waveNum; i++) {
            //封装了二阶贝塞尔曲线,x1、y1 代表控制点的 x、y,即一个控制点动态图中的P1,x2、y2 代表目标点的 x、y
            mPath.quadTo(mWaveWidth * (num + 1) - distance, currentY - mWaveHight, mWaveWidth * (num + 2) - distance, currentY);
            mPath.quadTo(mWaveWidth * (num + 3) - distance, currentY + mWaveHight, mWaveWidth * (num + 4) - distance, currentY);
            num += 4;
        }

        distance += mWaveWidth / mWaveSpeed;
        distance = distance % (mWaveWidth * 4);
        //从上一个点已直线方式连接到坐标(width, height)
        mPath.lineTo(width, height);
        mPath.lineTo(0, height);
        //close相当于lineTo到最后一次moveTo的终点构成一条闭合路径
        mPath.close();
        canvas.drawPath(mPath, mPathPaint);

        int min = Math.min(width, height);
        backgroundBitmap = Bitmap.createScaledBitmap(backgroundBitmap, min, min, false);
        //取上层非交集部分与下层交集部分
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
        canvas.drawBitmap(backgroundBitmap, 0, 0, paint);
        canvas.drawText(currentText, width / 2, height / 2, mTextPaint);
        return bitmap;
    }
        最后,代码传送门

      参考资料:
      1、http://mp.weixin.qq.com/s?__biz=MzI0MjE3OTYwMg==&mid=2649548952&idx=1&sn=ade1f2793cac8b6c53b8a7f58309cce9&chksm=f11803e5c66f8af3ef715cbdde7d765a29f43ebbba05794bde43b4d29577ff5aaafc227f01ba&mpshare=1&scene=1&srcid=0327rKcoqaM094GwaNEfazgW#rd
      2、http://blog.csdn.net/tianjian4592/article/details/46955833


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值