Android SVG动画

Android 5.X SVG矢量动画机制

概要

Google在Android 5.X中增加了对SVG矢量图形的支持,首先大概了解一下SVG。

  • 可伸缩的矢量图形(Scalable Vector Graphics)
  • 使用XML格式定义图形
  • 图像放大或改变尺寸的情况下其图形质量不会有损失
  • 万维网联盟标准

总的来说SVG是一个绘图标准。与Bitmap对比,SVG最大的优点就是放大不会失真。

< path >标签

使用path标签创建svg,就像使用指令的方式来控件一只画笔。
常用的指令有:

  • M = moveto 移动绘制点
  • L = lineto 直线
  • H = horizontal lineto 水平线
  • V = vertical lineto 竖直线
  • C = curveto 三次贝塞尔曲线
  • S = smooth curveto 三次贝塞尔曲线
  • Q = quadratic Belzier curve 二次贝塞尔曲线
  • T = smooth quadratic Belzier curveto 映射前面路径后的终点
  • A = elliptical Arc 圆弧
  • Z = closepath 闭合

    注释:以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。

Android中使用SVG

Coogle在Android5.x中提供了下面两个新的Api来帮助支持SVG。

  • VectorDrawable
  • AnimatedVectorDrawable
VectorDrawable

其中,VectorDrawable让你可一个创建基于XML的SVG的图形,并结合AnimatedVectorDrawable来实现动画效果。例如要实现下图效果。

这里写图片描述

简单分析:一条下滑线和一个搜索的logo,我就可以用代码这样定义:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="320dp"
    android:height="45dp"
    android:viewportWidth="320"
    android:viewportHeight="45">

    <path
        android:name="search"
        android:strokeLineCap="round"
        android:strokeColor="#f8fc03"
        android:strokeWidth="2"
        android:pathData="
        M 290,30
        A 15,15,0,1,1,291,29
        L 300,42"></path>

    <path
        android:name="bar"
        android:strokeLineCap="round"
        android:strokeColor="#f8fc03"
        android:strokeWidth="2"
        android:pathData="
        M 10,42
        L 300,42"></path>

</vector>

代码中标签有两个重要标签path,vector。

vector:用于定义整个画布。
width:画布的宽度。
height:画布的高度。
viewportWidth:将具体的宽度划分成相对的单位单元。320dp分成320个单元。
viewportHeight:将具体的高度划分成相对的单元单位。45dp被分成48个单元。
(ps,高宽保持相对比例,否则会发生图片扭曲)
path:用于画出具体的图案,类似于画笔。
name:声明一个标记。类似于id。 便于对其做动画的时候可以找到该节点。
pathData:矢量图SVG 的描述
strokeWidth:画笔的宽度
strokeColor:画笔的颜色
strokeAlpha:透明度
strokeLineCap:画出线条的结束点的形状。正方向或圆角矩形。。。

AnimatedVectorDrawable

图形生成后,添加如下动画

这里写图片描述

动画分析

  • 当点击输入框时,搜索logo消失,下滑线从右到左生成。
  • 当点击非输入框时,下划线从左到右消失,搜索logo生成。

动画一的实现:

drawable/draw_animator1.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vec_search">

    <target
        android:animation="@animator/search_anim_empty"
        android:name="search"></target>

    <target
        android:animation="@animator/bar_anim_fill"
        android:name="bar"></target>

</animated-vector>

通过上面代码可知,AnimatedVectorDrawable相当于一个胶水的作用,将
VectorDrawable与Animator连接起来。

< animated-vector>
drawable:目标SVG.
< targer>:对于SVG中的每一个< path >定义不同的动画。
name: 目标文件的标识。
animation:动画。
< /targer>
< /animated-vector>

animator/search_anim_empty.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueType="floatType"
    android:propertyName="trimPathStart"
    android:valueFrom="0"
    android:valueTo="1"
    android:duration="1000"
    android:interpolator="@android:interpolator/linear_out_slow_in"></objectAnimator>

动画属性trimPathEnd这个字段之前未出现过。它也是的一个属性,其决定的是节点所画出线条显示的百分比。 0~1 代表 从开始到结束显示的百分比。

同时也有一个trimPathStart,这个字段显示的也是百分比。不过其表示的是不显示的百分比。0~1代表从开始隐藏的百分比。

ps: 动画定义的都是属性动画,所以需要放在animator文件夹中
ps: 如果要改变path本身,propertyName=”pathData”valueType=”pathType”

animator/bar_anim_fill.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueType="floatType"
    android:propertyName="trimPathStart"
    android:valueFrom="1"
    android:valueTo="0"
    android:duration="1000"
    android:interpolator="@android:interpolator/linear_out_slow_in"></objectAnimator>

动画二实现:

drawable/draw_animator2.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vec_search">

    <target
        android:animation="@animator/search_anim_fill"
        android:name="search"></target>

    <target
        android:animation="@animator/bar_anim_empty"
        android:name="bar"></target>

</animated-vector>

animator/search_anim_fill.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueType="floatType"
    android:propertyName="trimPathStart"
    android:valueFrom="1"
    android:valueTo="0"
    android:duration="1000"
    android:interpolator="@android:interpolator/linear_out_slow_in"></objectAnimator>

animator/bar_anim_empty.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:valueType="floatType"
    android:propertyName="trimPathStart"
    android:valueFrom="0"
    android:valueTo="1"
    android:duration="1000"
    android:interpolator="@android:interpolator/linear_out_slow_in"></objectAnimator>

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:onClick="lost_foucs">

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true">

        <ImageView
            android:id="@+id/img_svg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/vec_anim_search"/>

        <EditText
            android:id="@+id/et"
            android:layout_width="250dp"
            android:layout_height="45dp"
            android:background="@android:color/transparent"/>

    </FrameLayout>

</RelativeLayout>

java代码:

public class SVGActivity extends Activity{
    ImageView img;
    private EditText editText;

    private AnimatedVectorDrawable animate1;
    private AnimatedVectorDrawable animate2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_svg);
        img = (ImageView) findViewById(R.id.img_svg);
        editText = (EditText) findViewById(R.id.et);

        animate1 = (AnimatedVectorDrawable)       getResources().getDrawable(R.drawable.draw_animator1);
        animate2 = (AnimatedVectorDrawable) getResources().getDrawable(R.drawable.draw_animator2);

        editText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                img.setImageDrawable(animate1);
                animate1.start();
            }
        });
    }

    public void lost_foucs(View view){
        img.setImageDrawable(animate2);
        animate2.start();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("wangGV", "onResume()");
//        throw new NullPointerException();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("wangGV", "onDestroy()");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值