Android developerAndroidAndroid自定义控件

Android Path学习笔记

2016-02-19  本文已影响2721人  前世小书童
简单说说

<p>
  Path是android中用来封装几何学路径的一个类,因为Path在图形绘制上占的比重还是相当大的,所以经过学习后,对Path中方法进行总结使用与应用

Path类的方法

<p>

图1 Path方法

Path中的方法相对较多,不对期进行一一说明,将平时用的较多的方法拿出来着重说明

1) 将路径连接至某个坐标点

  lineTo(float x, float y)

**(2)改变起始点的位置 **

  moveTo(float x, float y)

(3)闭合路径

  close() 

(4)路径重置

  reset()

(5)画弧形路径

  arcTo(float left, float top, float right, float bottom, RectF oval, float startAngle, float     sweepAngle,boolean forceMoveTo)
  arcTo (RectF oval, float startAngle, float sweepAngle)
  arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)

参数boolean forceMoveTo,当值为true时将会把弧的起点作为Path的起点

(6)**addXXX方法 **直接往Path中添加一些曲线

添加矩形曲线

  addRect(RectF rect,Direction dir)
  addRect(float left, float top, float right, float bottom,Direction dir)

添加椭圆形曲线

  addOval(RectF oval,Direction dir)
  addOval(float left, float top, float right, float bottom,Direction dir)

添加圆形曲线

  addCircle(float x, float y, floatradius,Direction dir)

添加弧形曲线

  addArc(RectF oval, float startAngle, float sweepAngle)
  addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)

添加圆角矩形曲线

  addRoundRect(RectF rect, float rx, float ry,Direction dir)
  addRoundRect(float left, float top, float right, float bottom, float rx, float ry,Direction dir)
  addRoundRect(RectF rect, float[] radii,Direction dir)
  addRoundRect(float left, float top, float right, float bottom, float[] radii,Direction dir)

添加path

  addPath(Path src, float dx, float dy)
  addPath(Path src)
  addPath(Path src,Matrix matrix)
而上面这些方法搭配一起就会碰撞出奇妙的火花

<p>
比如

图2 Path绘制图

亦或这个

图3 Path绘制图

还有这个

图4 Path绘制图

好吧我承认这个是我画的,确实比例有问题。。。

也许很多人会觉得利用Path来绘制图像代码量很大而且需要计算的数据也很多,但是我觉得的基本用法还是需要了解也熟练使用的

接下来要介绍的则是Path中的大招,这个方法会带来很多很赞的体验与设计

(7)贝塞尔曲线
<p>
什么是贝塞尔曲线就不做概述了,简单说就是只需要一个起点、一个终点和至少零个控制点则可定义一个贝赛尔曲线
<p>
一阶贝赛尔曲线

图5 一阶贝塞尔曲线公式

其中B(t)为时间为t时点的坐标,P0为起点、Pn为终点,曲线图如下

图6 一阶贝塞尔曲线图

二阶贝塞尔曲线

二阶贝赛尔曲线的一个明显特征是其拥有一个控制点,通过控制点来控制曲线的走向

图7 二阶贝塞尔曲线公式

对应的二阶曲线图如下

图8 二阶贝塞尔曲线图

在Android Path中存在对应的方法来实现二阶贝塞尔曲线

    quadTo(float x1, floaty1, float x2, float y2)  其中x1,y1为控制点,x2,y2为终点

利用好二阶贝塞尔曲线其实可以玩转出一些比较赞的效果了

比如下面的波浪效果

图9 贝塞尔二阶曲线实现的波浪效果

代码实现角度也很简单
<p>

         /* 
         * 设置Path起点 
         * 注意我将Path的起点设置在了控件的外部看不到的区域 
         * 如果我们将起点设置在控件左端x=0的位置会使得贝塞尔曲线变得生硬 
         * 至于为什么刚才我已经说了 
         * 所以我们稍微让起点往“外”走点 
         */  
        mPath.moveTo(-1 / 4F * vWidth, waveY);  
  
        /* 
         * 以二阶曲线的方式通过控制点连接位于控件右边的终点 
         * 终点的位置也是在控件外部 
         * 我们只需不断让ctrX的大小变化即可实现“浪”的效果 
         */  
        mPath.quadTo(ctrX, ctrY, vWidth + 1 / 4F * vWidth, waveY);  
  
        // 围绕控件闭合曲线  
        mPath.lineTo(vWidth + 1 / 4F * vWidth, vHeight);  
        mPath.lineTo(-1 / 4F * vWidth, vHeight);  
        mPath.close();  
  
        canvas.drawPath(mPath, mPaint);  
  
        /* 
         * 当控制点的x坐标大于或等于终点x坐标时更改标识值 
         */  
        if (ctrX >= vWidth + 1 / 4F * vWidth) {  
            isInc = false;  
        }  
        /* 
         * 当控制点的x坐标小于或等于起点x坐标时更改标识值 
         */  
        else if (ctrX <= -1 / 4F * vWidth) {  
            isInc = true;  
        }  
  
        // 根据标识值判断当前的控制点x坐标是该加还是减  
        ctrX = isInc ? ctrX + 20 : ctrX - 20;  
  
        /* 
         * 让“水”不断减少 
         */  
        if (ctrY <= vHeight) {  
            ctrY += 2;  
            waveY += 2;  
        }  
  
        mPath.reset();  
  
        // 重绘  
        invalidate();  

主要通过控制控制点与终点的位置不断的重绘产生波浪的形状

同样的某些下拉刷新的效果也是通过这样的方法去产生的比如

图10 贝塞尔二阶曲线实现的下拉效果

另外QQ“一键下班”功能其实也是基于二阶贝塞尔曲线实现的

图11 QQ一键下班功能

三阶贝塞尔曲线

三阶贝赛尔曲线则是拥有两个控制点,通过控制点来控制曲线的走向

图12 三阶贝塞尔曲线公式

对应的三阶曲线图如下

图13 三阶贝塞尔曲线图

在Android Path中存在对应的方法来实现二阶贝塞尔曲线

  cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)

其中x1,y1为第一个控制点,x2,y2为第二个控制点,x3,y3为终点

利用好三阶贝塞尔曲线其实可以有更多的效果了,在很多的App其实都有运用到了

比如百度贴吧的下拉刷新,美图的下拉刷新,Chrome的下拉刷新,慕课网的下拉刷新,其实都是基于三阶贝塞尔曲线来实现的

简单说下三阶贝塞尔运用的

第一种,和上述的二阶贝塞尔曲线一样,作为波浪使用

<p>
代表例子:慕课App的下拉刷新

图14 慕课App下拉刷新效果

这种实现其实与二阶波浪实现是一致的,控制好两个控制点即可以实现,不做代码的赘述

第二种则是通过闭合的路径产生特殊的效果

<p>
比如说下面这个例子

图15 闭合路径产生的效果

这个效果怎么实现的呢?
<p>
后面给出相关实现的代码

(8)PathMeasure

<p>
PathMeasure其实是测量Path的一个类,通过PathMeasure可以实现一些比较复杂的路径运动效果

 mPathMeasure = new PathMeasure(mPath, true);  
//设置运动的路径点
 mCurrentPosition = new float[2];  
  ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());   
  valueAnimator.setDuration(duration);  
  valueAnimator.addUpdateListener(new AnimatorUpdateListener() {  
  
       @Override  
       public void onAnimationUpdate(ValueAnimator animation) {  
       float value = (Float) animation.getAnimatedValue();  
       // 获取当前点坐标封装到mCurrentPosition  
       mPathMeasure.getPosTan(value, mCurrentPosition, null);  
       postInvalidate();  
    }  
  });  
  valueAnimator.start();    

通过PathMeasure可以实现如下的效果

图16 Path路径运动效果 图17 Path路径运动效果

到此Path中的大部分方法与使用应用都已经描述到了,由于是本人学习笔记,所以大部分的效果图都是来自于网络的分享,感谢各位大牛的分享

Reference

1.自定义控件其实很简单5/12From AigeStudio

2.Android 用Canvas 画几何图形,画出小黄人From 山言两语

3.Android雷达图(蜘蛛网图)绘制 From crazy__chen

4.慕课网app下拉刷新图标填充效果的实现From 安卓弟

5.【Android开源项目解析】QQ“一键下班”功能实现解析From 裸奔的凯子哥

6.四步实现ChromeLikeSwipeLayout效果From 我是Asha

7.三次贝塞尔曲线练习之弹性的圆From shadev

8.Path特效之PathMeasure打造万能路径动效From 学问积年而成

9.【Android开源项目解析】仿支付宝付款成功及"天女散花"效果实现From 裸奔的凯子哥

上一篇下一篇

猜你喜欢

热点阅读