Как анимировать 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 проблемы:

  1. Поскольку это единственный путь, он выглядит не очень хорошо. Нужно знать, как разбить его на 3 дорожки, чтобы каждый анимировал красиво.

  2. Кажется, все, что я использую в коде, от 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" - мы заставили линию снова исчезнуть, переместив начальную точку сверху вниз

Вы должны сделать аналогичную вещь с каждой стороны стрелки и упорядочить вещи соответствующим образом, чтобы получить желаемый эффект.

Другие вопросы по тегам