Youtube Play/pause android 上的动画矢量可绘制对象
Youtube Play/pause Animated Vector Drawable on android
我正在尝试使用 svgs 路径和动画矢量制作类似 youtube Play/Pause 的动画。
Strings.xml
<resources>
<string name="app_name">AnimatedSvgTest</string>
<string name="svg_triangle">
M0,0 L0,24 12,12 0,0
</string>
<string name="svg_pause">
M0,0 L0,24 M12,0 L12,24
</string>
</resources>
anim/path_morph.xml
:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="4000"
android:propertyName="pathData"
android:valueFrom="@string/svg_triangle"
android:valueTo="@string/svg_pause"
android:valueType="pathType" />
</set>
drawable/avd.xml
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_play_arrow_24dp">
<target
android:name="play"
android:animation="@anim/path_morph" />
</animated-vector>
drawable/ic_pause_arrow.xml
:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:pathData="@string/svg_pause"
android:strokeColor="#000"
android:strokeWidth="1.0" />
</vector>
drawable/ic_play_arrow.xml
:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportHeight="100.0"
android:viewportWidth="100.0">
<path
android:fillColor="#FF000000"
android:pathData="@string/svg_triangle" />
</vector>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageButton
android:id="@+id/button"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:src="@drawable/avd" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageButton button = (ImageButton) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Animatable animatable = (Animatable) button.getDrawable();
animatable.start();
}
});
}
}
但我仍然 Caused by: android.view.InflateException: Binary XML file line #2 Can't morph from
崩溃 :/
为此,您需要使路径兼容。将有多种方法可以做到这一点,具体取决于您希望实际过渡看起来像什么,您基本上可以使用一些技巧来确保这两个可绘制对象的 pathData
具有 相同的数字并且相同顺序的命令类型。在这种情况下,这意味着一个三角形是使用与两个矩形相同的路径格式制作的。
这里的另一个问题是,在三角形的情况下,您使用的是 fillColor,因此您在屏幕上看到的是在您绘制的路径中填充的内容,但暂停符号使用的是粗细为 1.0 的线条,所以你在屏幕上看到的实际上是两条粗线而不是填充形状。
我建议您更改此设置,以便两者都使用 fillColor 而不是彩色粗线,然后使路径兼容。
这是一个如何使它们兼容的示例。
目前不兼容的路径如下所示:
<string name="svg_triangle">
M0,0 L0,24 12,12 0,0
</string>
<string name="svg_pause">
M0,0 L0,24 M12,0 L12,24
</string>
它们不兼容,因为它们没有相同数量的 M
和 L
命令或相同数量的坐标。兼容路径如下所示:
<string name="svg_triangle">
M0,0 L0,24 12,12 0,0 M12,0 L12,0 12,0 12,0
</string>
<string name="svg_pause">
M0,0 L0,24 1,24 1,0 M12,0 L12,24 13,24 13,0
</string>
您应该注意到它们现在具有相同数量的 M
和 L
命令以及相同数量的坐标。
我已经将 M12,0 L12,0 12,0 12,0
添加到三角形的路径;这部分在屏幕上不可见,因为它并没有真正勾勒出一个形状,所有的点都在坐标 12,0 处。
对于暂停按钮,我对其进行了更多更改,之前它只有两行,现在我改为勾勒出形状。为了看起来正确,将 drawable/ic_pause_arrow.xml
的 <path>
部分更改为使用与播放相同的 fillColor,因此:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="@string/svg_pause"/>
</vector>
您现在应该有两个兼容变形的矢量绘图。请注意,我没有专门尝试过转换,它可能看起来不像您想要的那样,因此可能需要进行一些实验。 I wrote a tutorial on my blog 我认为这是相关的,我详细介绍了一些更复杂的示例,以及有关问题和技术(包括源代码)的更多背景。希望这有帮助。
我正在尝试使用 svgs 路径和动画矢量制作类似 youtube Play/Pause 的动画。
Strings.xml
<resources>
<string name="app_name">AnimatedSvgTest</string>
<string name="svg_triangle">
M0,0 L0,24 12,12 0,0
</string>
<string name="svg_pause">
M0,0 L0,24 M12,0 L12,24
</string>
</resources>
anim/path_morph.xml
:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="4000"
android:propertyName="pathData"
android:valueFrom="@string/svg_triangle"
android:valueTo="@string/svg_pause"
android:valueType="pathType" />
</set>
drawable/avd.xml
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_play_arrow_24dp">
<target
android:name="play"
android:animation="@anim/path_morph" />
</animated-vector>
drawable/ic_pause_arrow.xml
:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:pathData="@string/svg_pause"
android:strokeColor="#000"
android:strokeWidth="1.0" />
</vector>
drawable/ic_play_arrow.xml
:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportHeight="100.0"
android:viewportWidth="100.0">
<path
android:fillColor="#FF000000"
android:pathData="@string/svg_triangle" />
</vector>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageButton
android:id="@+id/button"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:src="@drawable/avd" />
</RelativeLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageButton button = (ImageButton) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Animatable animatable = (Animatable) button.getDrawable();
animatable.start();
}
});
}
}
但我仍然 Caused by: android.view.InflateException: Binary XML file line #2 Can't morph from
崩溃 :/
为此,您需要使路径兼容。将有多种方法可以做到这一点,具体取决于您希望实际过渡看起来像什么,您基本上可以使用一些技巧来确保这两个可绘制对象的 pathData
具有 相同的数字并且相同顺序的命令类型。在这种情况下,这意味着一个三角形是使用与两个矩形相同的路径格式制作的。
这里的另一个问题是,在三角形的情况下,您使用的是 fillColor,因此您在屏幕上看到的是在您绘制的路径中填充的内容,但暂停符号使用的是粗细为 1.0 的线条,所以你在屏幕上看到的实际上是两条粗线而不是填充形状。
我建议您更改此设置,以便两者都使用 fillColor 而不是彩色粗线,然后使路径兼容。
这是一个如何使它们兼容的示例。 目前不兼容的路径如下所示:
<string name="svg_triangle">
M0,0 L0,24 12,12 0,0
</string>
<string name="svg_pause">
M0,0 L0,24 M12,0 L12,24
</string>
它们不兼容,因为它们没有相同数量的 M
和 L
命令或相同数量的坐标。兼容路径如下所示:
<string name="svg_triangle">
M0,0 L0,24 12,12 0,0 M12,0 L12,0 12,0 12,0
</string>
<string name="svg_pause">
M0,0 L0,24 1,24 1,0 M12,0 L12,24 13,24 13,0
</string>
您应该注意到它们现在具有相同数量的 M
和 L
命令以及相同数量的坐标。
我已经将 M12,0 L12,0 12,0 12,0
添加到三角形的路径;这部分在屏幕上不可见,因为它并没有真正勾勒出一个形状,所有的点都在坐标 12,0 处。
对于暂停按钮,我对其进行了更多更改,之前它只有两行,现在我改为勾勒出形状。为了看起来正确,将 drawable/ic_pause_arrow.xml
的 <path>
部分更改为使用与播放相同的 fillColor,因此:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="@string/svg_pause"/>
</vector>
您现在应该有两个兼容变形的矢量绘图。请注意,我没有专门尝试过转换,它可能看起来不像您想要的那样,因此可能需要进行一些实验。 I wrote a tutorial on my blog 我认为这是相关的,我详细介绍了一些更复杂的示例,以及有关问题和技术(包括源代码)的更多背景。希望这有帮助。