Как анимировать VectorDrawable в виде жидкости?
Фон
Предположим, у меня есть VectorDrawable, который выглядит как стрелка сверху-> вниз:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"
android:fillColor="#010101"/>
</vector>
Я хочу показать анимацию, которая выглядит как жидкость, которую она вылила, так что сначала ничего не отображается, затем верхняя область, затем также средняя область, а затем нижняя часть. После того, как все показано, оно начинает скрываться, так что верхняя часть становится скрытой, а затем средняя и нижняя.
Вот набросок того, что я имею в виду:
Эта проблема
Есть несколько уроков по анимации VectorDrawable, и кажется, что они требуют большого понимания векторов, без простого способа сделать это.
Что я нашел
Я нашел инструмент, который можно использовать для этого, но я не понимаю, как его использовать, и ссылка на примеры в настоящее время не работает:
https://romannurik.github.io/AndroidIconAnimator/
Я также нашел несколько уроков по анимации VectorDrawable в целом, но я не могу найти это конкретное объяснение анимации:
http://www.androiddesignpatterns.com/2016/11/introduction-to-icon-animation-techniques.html
Эта ссылка, в частности, имеет представление о том, что я должен использовать. Я думаю, что я должен использовать "trimPathStart", "trimPathEnd", "trimPathOffset" или, возможно, "clip-path" .
Пример анимации, который у них есть, показывает, что это может быть так:
Но я не могу найти, как это сделать.
Вопрос
Как я могу применить такую анимацию на VectorDrawable?
Будет ли это работать на старых версиях Android, используя библиотеку поддержки?
РЕДАКТИРОВАТЬ: мне удалось анимировать стрелку, но у него есть 2 проблемы:
Поскольку это единственный путь, он выглядит не очень хорошо. Нужно знать, как разбить его на 3 дорожки, чтобы каждый анимировал красиво.
Кажется, все, что я использую в коде, от API 21 и выше. Я сделал это, посмотрев на ссылку, которую я написал ранее (здесь), и мне нужно знать, как поддерживать более старые версии.
Вот код:
Рез / рисуем /vector_animation.xml
<animated-vector
xmlns:aapt="http://schemas.android.com/aapt"
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_darkblue_arrow">
<target android:name="a_stroke">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="5000"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="trimPathEnd"
android:startOffset="1300"
android:valueFrom="0"
android:valueTo="1"/>
</aapt:attr>
</target>
</animated-vector>
Рез / рисуем /vector.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:name="a_stroke"
android:fillColor="#010101"
android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"/>
</vector>
разреш / макет / activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="200dp"
android:layout_height="200dp"
android:contentDescription="@null"
android:src="@drawable/vector_animation"/>
</FrameLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Animatable cursiveAvd = ((Animatable) ((ImageView) findViewById(R.id.imageView)).getDrawable());
cursiveAvd.stop();
cursiveAvd.start();
}
}
РЕДАКТИРОВАТЬ: я сделал простую стрелку с тремя путями VectorDrawable и успешно анимировал ее.
Вот созданный мной VectorDrawable:
ic_drawing.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="210dp"
android:height="297dp"
android:viewportHeight="1052.3622"
android:viewportWidth="744.0945">
<path
android:name="main_line"
android:fillColor="#00000000"
android:pathData="M742.6,9.7C313,-8.4 316.2,860.8 316.2,860.8"
android:strokeAlpha="1"
android:strokeColor="#000000"
android:strokeLineCap="butt"
android:strokeLineJoin="miter"
android:strokeWidth="5.32507801"/>
<path
android:name="left_line"
android:fillColor="#00000000"
android:pathData="m314.3,846.6c-211.4,-254.3 -160,-294.3 -160,-294.3"
android:strokeAlpha="1"
android:strokeColor="#000000"
android:strokeLineCap="butt"
android:strokeLineJoin="miter"
android:strokeWidth="5"/>
<path
android:name="right_line"
android:fillColor="#00000000"
android:pathData="M320,843.8C364.2,751.2 437.4,670.7 471.4,566.6"
android:strokeAlpha="1"
android:strokeColor="#000000"
android:strokeLineCap="butt"
android:strokeLineJoin="miter"
android:strokeWidth="5"/>
</vector>
vector_animation2.xml
<animated-vector
xmlns:aapt="http://schemas.android.com/aapt"
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_drawing">
<target android:name="main_line">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="5000"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="trimPathEnd"
android:startOffset="1300"
android:valueFrom="0"
android:valueTo="1"/>
</aapt:attr>
</target>
<target android:name="left_line">
<aapt:attr name="android:animation">
<objectAnimator
android:startDelay="5000"
android:duration="5000"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="trimPathEnd"
android:startOffset="1300"
android:valueFrom="0"
android:valueTo="1"/>
</aapt:attr>
</target>
<target android:name="right_line">
<aapt:attr name="android:animation">
<objectAnimator
android:startDelay="5000"
android:duration="5000"
android:interpolator="@android:interpolator/fast_out_slow_in"
android:propertyName="trimPathEnd"
android:startOffset="1300"
android:valueFrom="0"
android:valueTo="1"/>
</aapt:attr>
</target>
</animated-vector>
Итак, он работает хорошо, но работает только на более новых версиях Android, и я все еще хотел бы знать, как красиво разделить существующий VectorDrawable вместо создания нового.
1 ответ
Есть несколько способов получить похожий вид, но не все будут обратно совместимы с помощью библиотеки поддержки. По этой причине я бы рекомендовал использовать trimPathStart
а также trimPathEnd
,
Я опишу подход, который я выберу, а не окончательное решение (может занять много времени!).
Первая проблема в начале работы заключается в том, что ваш оригинальный VectorDrawable не очень подходит для этого типа анимации!
Рисуемое в вопросе описывает контур фигуры (т.е. девять линий, очерчивающих стрелку) и отображает заливку. Что было бы лучше для наших целей, так это нарисовать три линии, где нет fillColor
и вместо этого мы устанавливаем, как строки должны отображаться с помощью strokeColor
а также strokeWidth
,
Это должен быть простой VectorDrawable с тремя <path>
элементы: по одному для вертикальной линии и по одному для каждой стороны наконечника стрелки.
Получив это, вы можете подумать о том, как вы хотите, чтобы ваша анимация выглядела. trimPathStart
а также trimPathEnd
Должны быть значения от 0 до 1, где 0 - начало пути, а 1 - конец. Рассмотрим вертикальную линию, проведенную сверху вниз:
trimPathStart="0"
trimPathEnd="0"
- мы не можем видеть линию
-> оживить
trimPathStart="0"
trimPathEnd="1"
- мы нарисовали линию сверху вниз
-> оживить
trimPathStart="1"
trimPathEnd="1"
- мы заставили линию снова исчезнуть, переместив начальную точку сверху вниз
Вы должны сделать аналогичную вещь с каждой стороны стрелки и упорядочить вещи соответствующим образом, чтобы получить желаемый эффект.