Skip to content

Commit 9701d53

Browse files
committed
vector静态使用和动态使用,以及二阶贝塞尔曲线的模拟
1 parent e29109f commit 9701d53

39 files changed

+758
-15
lines changed

README.md

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,198 @@
1+
2+
3+
4+
15
# AndroidAnimation
6+
27
Android 高级动画Demo
8+
9+
### VectorDrawable基础知识
10+
11+
#### SVG和Vector差异
12+
13+
- SVG————前端中使用,是一套语法规范
14+
15+
- Vector————在Android中使用
16+
17+
> Vector只实现了SVG语法中的Path标签
18+
19+
#### Vector的常用语法
20+
21+
> M = moveto(M X,Y) : 将画笔移动到指定的坐标位置
22+
>
23+
> L = lineto(L X,Y) : 画直线到指定的坐标位置
24+
>
25+
> Z = closepath() : 关闭路径
26+
>
27+
> H = horizontal lineto(H X) : 画水平线到指定的X坐标
28+
>
29+
> Y = vertical lineto(V Y) : 画垂直线到指定的Y坐标
30+
31+
#### SVG编辑器
32+
33+
[SVG Editor](http://editor.method.ac/)
34+
35+
![](img\svg_editor.png)
36+
37+
##### SVG转换VectorDrawable
38+
39+
- 由于Android原生支持的是Vector,所以可以将SVG转换成vector——[SVG2Android](http://inloop.github.io/svg2android/)
40+
41+
![](img\svg2Android.png)
42+
43+
- 也可以通过Android studio自带的**Vector Asset**工具将SVG转换成vector,在**res**下的**drawable**目录右击选择**new**,然后选择**Vector Asset**即可。
44+
45+
![](img\vector_asset.jpg)
46+
47+
###### 转换效果对比
48+
49+
![](img\result.jpg)
50+
51+
##### SVG图片资源
52+
53+
[SVG图片资源](http://www.iconfont.cn/plus/collections/index)
54+
55+
![](img\svg_download.png)
56+
57+
#### VectorDrawable兼容性
58+
59+
- Android L,只兼容minSDK>=21的版本
60+
61+
> 几乎没有兼容性
62+
63+
- Gradle Plugin 1.5
64+
65+
- 设备版本>=21——使用Vector
66+
- 设备版本<21——将Vector转换为PNG
67+
68+
> 增加了兼容的成本,效果也有限
69+
70+
- AppCompat23.2
71+
72+
- 静态Vector支持Android2.1+
73+
- 动态Vector支持Android3.0+
74+
75+
> 几乎可以兼容大部分使用场景
76+
77+
#### 使用静态的VectorDrawable
78+
79+
- 配置引用和参数
80+
81+
app的gradle文件中加入
82+
```kotlin
83+
android {
84+
...
85+
defaultConfig {
86+
...
87+
vectorDrawables.useSupportLibrary = true
88+
}
89+
}
90+
```
91+
92+
- Vector图像标签
93+
94+
```xml
95+
<!-- 绘制一个矩形 -->
96+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
97+
android:width="48dp"
98+
android:height="48dp"
99+
android:viewportWidth="200"
100+
android:viewportHeight="200">
101+
102+
<path
103+
android:name="square"
104+
android:fillColor="#272636"
105+
android:pathData="M50,50 L100,50 L100,100 L50,100z"/>
106+
</vector>
107+
```
108+
109+
- **android:width\android:height** : 定义图片的宽高
110+
- **android:viewportWidth\android:viewportHeight** : 定义图像被划分的比例大小
111+
112+
- 在控件中使用
113+
114+
- **ImageView\ImageButton**中使用:直接**android:src(minSDK>=21)\app:srcCompat=”@drawable/vector_image“(minSDK<21)**即可
115+
116+
- **Button**中使用:需要通过selector来进行设置,并开启下面的设置
117+
118+
```java
119+
static {
120+
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
121+
}
122+
```
123+
124+
> 如果没加静态代码块,5.0下会Crash5.0以上可以正常显示。
125+
126+
#### 使用动态的VectorDrawable
127+
128+
- 配置动画粘合剂————animated-vector
129+
130+
```xml
131+
<?xml version="1.0" encoding="utf-8"?>
132+
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/ic_arrows">
133+
<target
134+
android:animation="@animator/anim_left"
135+
android:name="left"/>
136+
<target
137+
android:animation="@animator/anim_right"
138+
android:name="right"/>
139+
</animated-vector>
140+
```
141+
142+
其中的**@animator/anim_left****@animator/anim_right**就是想要实现的属性动画效果。
143+
144+
- 属性动画
145+
146+
```xml
147+
<?xml version="1.0" encoding="utf-8"?>
148+
<objectAnimator
149+
xmlns:android="http://schemas.android.com/apk/res/android"
150+
android:duration="1000"
151+
android:interpolator="@android:interpolator/bounce"
152+
android:propertyName="translateX"
153+
android:repeatCount="infinite"
154+
android:repeatMode="reverse"
155+
android:valueFrom="0"
156+
android:valueTo="10"
157+
android:valueType="floatType">
158+
</objectAnimator>
159+
```
160+
161+
- 使用
162+
163+
Xml中使用,将animated-vector的xml文件设置给ImageView的src属性(minSDK>=21)或app:srcCompat(minSDK<21)属性
164+
165+
```xml
166+
<ImageView
167+
android:id="@+id/iv_arrow"
168+
android:layout_width="100dp"
169+
android:layout_height="100dp"
170+
android:src="@drawable/arrow_anim"
171+
android:contentDescription="@string/app_name" />
172+
```
173+
174+
代码中启动动画即可
175+
176+
```java
177+
Drawable drawable = imageView.getDrawable();
178+
if (drawable instanceof Animatable) {
179+
((Animatable) drawable).start();
180+
}
181+
```
182+
183+
##### 动态VectorDrawable兼容性问题
184+
185+
- 向下兼容问题
186+
- **Path Morphing**——路径转换动画,在Android pre-L版本下是无法使用
187+
- **Path Interpolation**——路径差值器,在Android pre-L版本只能使用系统提供的差值器,不能自定义
188+
- 向上兼容问题
189+
- 抽取string兼容问题——不支持从strings.xml中读取<PathData>
190+
191+
#### VectorDrawable使用场景
192+
193+
- Vector vs Bitmap
194+
1. Bitmap的绘制效率并不一定会比Vector高,他们有一定的平衡点,当Vector比较简单时,其效率是一定比Bitmap高的,所以,为了保证Vector的高效率,Vector需要更加简单,PathData更加标准、精简,当Vector的图像变得非常复杂时,就需要使用Bitmap来代替了。
195+
2. Vector适用于ICON、Button、ImageView等图标等小ICON,或者是需要动画的效果,由于Bitmap在GPU中有缓存功能,而Vector并没有,所以Vector图像不能做频繁的重绘。
196+
3. Vector图像过于复杂时,不仅仅要注意绘制效率,初始化效率也是需要考虑的重要因素。
197+
4. SVG加载速度会快于PNG,但渲染速度会低于PNG,毕竟PNG有硬件加速,但平均下来,加载速度的提升弥补了渲染的速度缺陷。
198+

app/build.gradle

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ android {
1010
versionCode 1
1111
versionName "1.0"
1212
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13+
14+
vectorDrawables.useSupportLibrary = true
1315
}
1416
buildTypes {
1517
release {
@@ -21,9 +23,9 @@ android {
2123

2224
dependencies {
2325
implementation fileTree(dir: 'libs', include: ['*.jar'])
24-
implementation 'androidx.appcompat:appcompat:1.0.2'
26+
implementation 'androidx.appcompat:appcompat:1.1.0'
2527
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
2628
testImplementation 'junit:junit:4.12'
27-
androidTestImplementation 'androidx.test:runner:1.1.1'
28-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
29+
androidTestImplementation 'androidx.test:runner:1.2.0'
30+
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
2931
}

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
android:roundIcon="@mipmap/ic_launcher_round"
1010
android:supportsRtl="true"
1111
android:theme="@style/AppTheme">
12+
<activity android:name=".SecondBezierDemoActivity"></activity>
13+
<activity android:name=".VectorDemoActivity" />
1214
<activity android:name=".MainActivity">
1315
<intent-filter>
1416
<action android:name="android.intent.action.MAIN" />

app/src/main/java/com/hyd/animationart/MainActivity.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,27 @@
22

33
import androidx.appcompat.app.AppCompatActivity;
44

5+
import android.content.Intent;
56
import android.os.Bundle;
7+
import android.view.View;
68

7-
public class MainActivity extends AppCompatActivity {
9+
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
810

911
@Override
1012
protected void onCreate(Bundle savedInstanceState) {
1113
super.onCreate(savedInstanceState);
1214
setContentView(R.layout.activity_main);
15+
16+
findViewById(R.id.vector_demo).setOnClickListener(this);
17+
findViewById(R.id.second_bezier).setOnClickListener(this);
18+
}
19+
20+
@Override
21+
public void onClick(View v) {
22+
if (v.getId() == R.id.vector_demo) {
23+
startActivity(new Intent(this, VectorDemoActivity.class));
24+
} else if (v.getId() == R.id.second_bezier) {
25+
startActivity(new Intent(this, SecondBezierDemoActivity.class));
26+
}
1327
}
1428
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.hyd.animationart;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
5+
import android.os.Bundle;
6+
7+
public class SecondBezierDemoActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_second_bezier_demo);
13+
}
14+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.hyd.animationart;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
import androidx.appcompat.app.AppCompatDelegate;
5+
6+
import android.content.Intent;
7+
import android.graphics.drawable.Animatable;
8+
import android.graphics.drawable.Animatable2;
9+
import android.graphics.drawable.Drawable;
10+
import android.os.Bundle;
11+
import android.view.View;
12+
import android.widget.ImageView;
13+
14+
public class VectorDemoActivity extends AppCompatActivity {
15+
16+
static {
17+
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
18+
}
19+
20+
@Override
21+
protected void onCreate(Bundle savedInstanceState) {
22+
super.onCreate(savedInstanceState);
23+
setContentView(R.layout.activity_vector_demo);
24+
25+
ImageView arrow = findViewById(R.id.iv_arrow);
26+
final ImageView square = findViewById(R.id.iv_square);
27+
final ImageView searchBar = findViewById(R.id.iv_search_bar);
28+
final ImageView star = findViewById(R.id.iv_star);
29+
final ImageView fiveStar = findViewById(R.id.iv_five_star);
30+
init(arrow);
31+
square.postDelayed(new Runnable() {
32+
@Override
33+
public void run() {
34+
init(square);
35+
}
36+
}, 1000);
37+
38+
searchBar.postDelayed(new Runnable() {
39+
@Override
40+
public void run() {
41+
init(searchBar);
42+
}
43+
}, 1000);
44+
45+
star.postDelayed(new Runnable() {
46+
@Override
47+
public void run() {
48+
init(star);
49+
}
50+
}, 1000);
51+
fiveStar.postDelayed(new Runnable() {
52+
@Override
53+
public void run() {
54+
init(fiveStar);
55+
}
56+
}, 1000);
57+
}
58+
59+
private void init(ImageView imageView) {
60+
Drawable drawable = imageView.getDrawable();
61+
if (drawable instanceof Animatable) {
62+
((Animatable) drawable).start();
63+
}
64+
}
65+
}
66+

0 commit comments

Comments
 (0)