利用 SVG 动画 实现 - 搜索框动画
1. SVG 动画是什么?
- SVG 的全称是 Scalable Vector Graphics (可缩放矢量图形〉,是专门用于网络的矢量图形标准;
- 与矢量图相对应的是位图, Bitmap 就是位图,它由一个个像素点组成,当图片放大到一定大小时, 就会出现马赛克现象;
- 优点:
使用XML 格式定义图形,可被非常多的工具读取和修改( 比如记事本)。
由点来存储,由计算机根据点信息绘图, 不会失真, 无须根据分辨率适配多套图标。
占用空间明显比 Bitmap 小。比如一张500px × 500px 的图像, 转成 SVG 后占用的空间大小是 20KB , 而 PNG 图片则需要 732KB 的空间。
可以转换为 Path 路径,与 Path 动画相结合, 可以形成更丰富的动画。
2. 在 Android 中引入 SVG 图像
在 Android 中是不支持 SVG 图像解析的,我们必须将 SVG 图像转换为 ve ctor 标签描述,这里有两种方法。
-
方法一:在线转换
直接将 SVG 图像时拖入在线转换网站:http://inloop.github.io/svg2android/
,即可转换出对应的vector 标签代码, -
方法二: 通过Android Studio 引入
3. 动画实现
-
引入兼容包
android { defaultConfig { //添加对Vector 兼容性的支持。 vectorDrawables.useSupportLibrary = true } }
-
注意:
-
在 Image View 、 ImageButton 中使用时,在布局文件中:
app : srcCompat= "@drawable/svg"
;或在代码中:iv.setimageResource(R . drawable.svg);
-
在 Button 中使用时,不能直接通过 app:srcCompat 属性来使用 Vector 图像,而需要通过selector 标签来使用;在布局文件中,
android:background = ”@drawable/selector_svg"
在代码中使用时还要在 onCreate() 方法上添加以下代码块;static { AppCompatDelegate . setCompatVectorFromResourcesEnabled(true); }
-
3.1 准备 SVG 图像
-
在
res\drawable\vector_search_bar.xml
中<?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="150dp" android:height="24dp" android:viewportWidth="150" android:viewportHeight="24"> <!--搜索 镜子--> <path android:name="search" android:pathData="M141,17 A9,9 0 1,1 142,16 L149,23" android:strokeWidth="2" android:strokeColor="#fff"/> <!--底部横线--> <path android:name="bar" android:trimPathStart="1" android:pathData="M0,23 L149,23" android:strokeWidth="2" android:strokeColor="#fff"/> </vector>
-
注意:
这里的搜索图形中A= elliptical Arc(A RX,RY,XROTATION,FLAG l ,FLAG2 ,X, Y); 弧线
各参数意义如下:
• RX,RY 指所有椭圆的半轴大小。 • XROTATION 指椭圆的X 轴和水平方向顺时针方向的夹角,可以想象成一个水平的椭 圆绕中心点顺时针旋转XROTATION 角度。 • FLAG !只有两个值, l 表示大角度弧度, 0 表示小角度弧度。 • FLAG2 只有两个值, 确定从起始点到终点的方向, l 表示顺时针, 0 表示逆时针。 • X, Y 为终点坐标。 有以下几点要注意: • 坐标轴以(0 ,0)点为中心, X 轴水平向右, y 轴水平向下。 • 所有指令大小写均可。大写表示绝对定位, 参照全局坐标系;小写表示相对定位,参 照父容器坐标系。 • 指令和数据间的空格可以省略。 • 同一指令出现多次可以只用一个。
-
android:trimPathStart="1"
表示,指定路径从哪里开始, 取值为0 ~ 1 ,表示路径开始位置的百分比。当取值为 0 时, 表示从头部开始;当取值为 1 时,整条路径不可见。
3.2 准备动画
-
对于底部横线而言, 从左至右逐渐减小,对起始点位置进行操作;在
res\animator\anim_bar_trim_start.xml
中;<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:propertyName="trimPathStart" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" />
-
对于搜索图形从无到有显示出来,对终点位置的操作;在
res\ animator\animsearch_trim_end.xml
。<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:propertyName="trimPathEnd" android:valueFrom="0" android:valueTo="1" android:valueType="floatType" />
-
通过 animated-vector 标签将 SVG 图像与动画关联起来;在
res\drawable\animated_vecotrs_earch.xml
中;<?xml version="1.0" encoding="utf-8"?> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vector_search_bar"> <target android:name="search" android:animation="@animator/anim_search_trim_end" /> <target android:name="bar" android:animation="@animator/anim_bar_trim_start" /> </animated-vector>
3.3 布局
-
使用 FrameLayout 标签;
-
将 两个控件,一个是 EditText ,另一个是 ImageView , 重叠在同一个位置;
-
EditText 用于输入文字, ImageView 用于做SVG 动画;
-
当EditText 获取焦点以后, ImageView 开始动画。
<FrameLayout android:layout_width="150dp" android:layout_height="match_parent"> <EditText android:id="@+id/edit" android:layout_width="150dp" android:layout_height="match_parent" android:background="@null" android:textColorHint="@android:color/darker_gray" android:hint="点击输入" /> <ImageView android:id="@+id/anim_img" android:layout_width="150dp" android:layout_height="match_parent" /> </FrameLayout>
3.4 开启动画
-
EditText 会默认获得焦点,所以将焦点放在 ImageView 上,然后当用
户单击 EditText 的时候, EditText 获得焦点,此时开始动画。private void searchAnim() { //将焦点放在 ImageView 上 iv_search_anim.setFocusable(true); iv_search_anim.setFocusableInTouchMode(true); iv_search_anim.requestFocus(); iv_search_anim.requestFocusFromTouch(); //当 EditText 获得焦点时开始动画 et_search.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { AnimatedVectorDrawableCompat animatedVectorDrawableCompat = AnimatedVectorDrawableCompat.create(LoadingActvity.this, R.drawable.animated_vecotr_search); iv_search_anim.setImageDrawable(animatedVectorDrawableCompat); ((Animatable) iv_search_anim.getDrawable()).start(); } } }); }
声明:本文整理自《《Android自定义控件开发入门与实战》_启舰》;