Skip to content

Android Vector以及贝塞尔曲线结合属性动画实现的Demo

License

Notifications You must be signed in to change notification settings

hydcoder/AndroidAnimation

Repository files navigation

AndroidAnimation

Android Vector以及贝塞尔曲线结合属性动画实现的Demo

VectorDrawable基础知识

SVG和Vector差异

  • SVG————前端中使用,是一套语法规范

  • Vector————在Android中使用

    Vector只实现了SVG语法中的Path标签

Vector的常用语法

M = moveto(M X,Y) : 将画笔移动到指定的坐标位置

L = lineto(L X,Y) : 画直线到指定的坐标位置

Z = closepath() : 关闭路径

H = horizontal lineto(H X) : 画水平线到指定的X坐标

Y = vertical lineto(V Y) : 画垂直线到指定的Y坐标

SVG编辑器

SVG Editor

SVG转换VectorDrawable
  • 由于Android原生支持的是Vector,所以可以将SVG转换成vector——SVG2Android

  • 也可以通过Android studio自带的Vector Asset工具将SVG转换成vector,在res下的drawable目录右击选择new,然后选择Vector Asset即可。

转换效果对比

SVG图片资源

SVG图片资源

VectorDrawable兼容性

  • Android L,只兼容minSDK>=21的版本

    几乎没有兼容性

  • Gradle Plugin 1.5

    • 设备版本>=21——使用Vector
    • 设备版本<21——将Vector转换为PNG

    增加了兼容的成本,效果也有限

  • AppCompat23.2

    • 静态Vector支持Android2.1+
    • 动态Vector支持Android3.0+

    几乎可以兼容大部分使用场景

使用静态的VectorDrawable

  • 配置引用和参数

    app的gradle文件中加入

      android {
          ...
          defaultConfig {
              ...
              vectorDrawables.useSupportLibrary = true
          }
      }
  • Vector图像标签

<path
 android:name="square"
 android:fillColor="#272636"
 android:pathData="M50,50 L100,50 L100,100 L50,100z"/>

```

  • android:width\android:height : 定义图片的宽高

  • android:viewportWidth\android:viewportHeight : 定义图像被划分的比例大小

  • 在控件中使用

    • ImageView\ImageButton中使用:直接**android:src(minSDK>=21)\app:srcCompat=”@drawable/vector_image“(minSDK<21)**即可

    • Button中使用:需要通过selector来进行设置,并开启下面的设置

      static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
      }

      如果没加静态代码块,5.0下会Crash。5.0以上可以正常显示。

使用动态的VectorDrawable

  • 配置动画粘合剂————animated-vector

    <?xml version="1.0" encoding="utf-8"?>
    <animated-vector              xmlns:android="http://schemas.android.com/apk/res/android"   android:drawable="@drawable/ic_arrows">  
        <target      
                android:animation="@animator/anim_left"      
                android:name="left"/>   
        <target      
                android:animation="@animator/anim_right"      
                android:name="right"/>
    </animated-vector>

    其中的**@animator/anim_left@animator/anim_right**就是想要实现的属性动画效果。

  • 属性动画

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator 
           xmlns:android="http://schemas.android.com/apk/res/android"
           android:duration="1000"   
           android:interpolator="@android:interpolator/bounce"   
           android:propertyName="translateX"   
           android:repeatCount="infinite"   
           android:repeatMode="reverse"   
           android:valueFrom="0"   
           android:valueTo="10"   
           android:valueType="floatType">
    </objectAnimator>
  • 使用

    Xml中使用,将animated-vector的xml文件设置给ImageView的src属性(minSDK>=21)或app:srcCompat(minSDK<21)属性

    <ImageView   
               android:id="@+id/iv_arrow"   
               android:layout_width="100dp"   
               android:layout_height="100dp"   
               android:src="@drawable/arrow_anim"   
               android:contentDescription="@string/app_name" />

    代码中启动动画即可

    Drawable drawable = imageView.getDrawable();
    if (drawable instanceof Animatable) {    
        ((Animatable) drawable).start();
    }
动态VectorDrawable兼容性问题
  • 向下兼容问题
    • Path Morphing——路径转换动画,在Android pre-L版本下是无法使用
    • Path Interpolation——路径差值器,在Android pre-L版本只能使用系统提供的差值器,不能自定义
  • 向上兼容问题
    • 抽取string兼容问题——不支持从strings.xml中读取

VectorDrawable使用场景

  • Vector vs Bitmap
    1. Bitmap的绘制效率并不一定会比Vector高,他们有一定的平衡点,当Vector比较简单时,其效率是一定比Bitmap高的,所以,为了保证Vector的高效率,Vector需要更加简单,PathData更加标准、精简,当Vector的图像变得非常复杂时,就需要使用Bitmap来代替了。
    2. Vector适用于ICON、Button、ImageView等图标等小ICON,或者是需要动画的效果,由于Bitmap在GPU中有缓存功能,而Vector并没有,所以Vector图像不能做频繁的重绘。
    3. Vector图像过于复杂时,不仅仅要注意绘制效率,初始化效率也是需要考虑的重要因素。
    4. SVG加载速度会快于PNG,但渲染速度会低于PNG,毕竟PNG有硬件加速,但平均下来,加载速度的提升弥补了渲染的速度缺陷。

Bezier曲线

Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。 曲线定义:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。 1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。

Android提供了二阶贝塞尔曲线和三阶贝塞尔曲线的 API,利用这两个api可以将更高阶的贝塞尔曲线的效果转换成多个二阶贝塞尔曲线和三阶贝塞尔曲线。

一阶贝塞尔曲线

描述:由 P0 至 P1 的连续点, 描述的一条线段

通用公式:

一阶贝塞尔曲线通用公式

B(t)为t时间下 点的坐标;

P0为起点,Pn为终点,Pi为控制点。

下同

效果图:

一阶贝塞尔曲线

二阶贝塞尔曲线

描述:由 P0 至 P1 的连续点 Q0,描述一条线段。由 P1 至 P2 的连续点 Q1,描述一条线段。由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。

通用公式:

一阶贝塞尔曲线通用公式

效果图:

二阶贝塞尔曲线

三阶贝塞尔曲线

通用公式:

一阶贝塞尔曲线通用公式

效果图:

五阶贝塞尔曲线

PathMeasure

初步认识

  • 初始化

    // 创建PathMeasure对象
    PathMeasure pathMeasure = new PathMeasure();
    // 设置关联Path
    // PathMeasure(Path path, boolean forceClosed);
    // forceClosed: 对绑定的Path不会产生任何影响,对PathMeasure的测量结果有影响
    pathMeasure.setPath(path, true);
  • API

    • getLength:获取计算的路径长度

    • getSegment:用于截取path中的一个片段

      public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo){...}
    • getPosTan:用于获取路径上某点的坐标及其切线的坐标

      public boolean getPosTan(float distance, float pos[], float tan[]) {...}
      
      // 通过getPosTan获取到某点切线的坐标去获取路径上某点的切线的角度
      (Math.atan2(tan[1], tan[0] * 180.0 / Math.PI))

About

Android Vector以及贝塞尔曲线结合属性动画实现的Demo

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages