Arkay
Arkay

Reputation: 469

Animating many parts of a vector drawable simultaneously

Using AnimatedVectorDrawables, one can apply certain animations to parts of a vectordrawable (see here). For example consider the vectordrawable, called vectordrawable.xml:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
 android:height="64dp"
 android:width="64dp"
 android:viewportHeight="600"
 android:viewportWidth="600" >
     <path
         android:name="path"
         android:fillColor="#000000"
         android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
</vector>

Which is a vectordrawable containing a single path (line). The desired animation would then be in a separate file, called animator.xml, for example:

<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
    android:duration="4000"
    android:propertyName="trimPathEnd"
    android:valueFrom="0"
    android:valueTo="1" />
</set>

Which would be animation showing the line being drawn. These two xml files would then feed into a third animatedvectordrawable xml file:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vectordrawable">
<target
    android:animation="@anim/animator"
    android:name="path" />

</animated-vector>

So the question is, what if your vectordrawable path contained a large number of paths, which you wanted to animate simultaneously? You could do this the long way and would have to give every path a different name, then target each and every path with the same animator in your animatedvectordrawable file. But if you've got over 20 paths, this would take a long time and be a messy solution.

You do have the option of enclosing a set of paths in a group, then target a single group. But the animations for groups are different to that of paths, i.e. animating trimPathEnd isn't possible for a group, thus you cannot apply this animation to a group of paths.

Upvotes: 1

Views: 2039

Answers (2)

Tarek360
Tarek360

Reputation: 1351

I want to suggest RichPath as well to do that but I don't recommend to call RichPathAnimator.animate() inside a long loop, you can achieve the same result in a better way, please check the 3rd step in this full example:

enter image description here

1- Normal vector_drawable.xml with 6 paths:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="256dp"
    android:viewportHeight="36.0"
    android:viewportWidth="36.0"
    android:width="256dp">

  <path
      android:pathData="M19.5,6.2l1.3-1.3c0.2-0.2,0.2-0.5,0-0.7c-0.2-0.2-0.5-0.2-0.7,0l-1.5,1.5C17.9,5.2,16.9,5,16,5c-1,0-1.9,0.2-2.7,0.6l-1.5-1.5c-0.2-0.2-0.5-0.2-0.7,0c-0.2,0.2-0.2,0.5,0,0.7l1.3,1.3C11,7.3,10,9,10,11h12C22,9,21,7.2,19.5,6.2z"
      android:strokeColor="#A4c639"
      android:strokeWidth="0.5"
      android:trimPathEnd="1"/>

  <path
      android:pathData="M13.9,8.9H13V8h0.9V8.9z"
      android:strokeColor="#A4c639"
      android:strokeWidth="0.5"
      android:trimPathEnd="1"/>

  <path
      android:pathData="M19,8.9h-0.9V8H19V8.9z"
      android:strokeColor="#A4c639"
      android:strokeWidth="0.5"
      android:trimPathEnd="1"/>

  <path
      android:pathData="M10,22c0,0.5,0.4,1,1,1h1v3.5c0,0.8,0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5V23h2v3.5c0,0.8,0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5V23h1c0.5,0,1-0.5,1-1V12H10V22z"
      android:strokeColor="#A4c639"
      android:strokeWidth="0.5"
      android:trimPathEnd="1"/>

  <path
      android:pathData="M24.5,12c-0.8,0-1.5,0.7-1.5,1.5v7c0,0.8,0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5v-7C26,12.7,25.3,12,24.5,12z"
      android:strokeColor="#A4c639"
      android:strokeWidth="0.5"
      android:trimPathEnd="1"/>

  <path
      android:pathData="M7.5,12C6.7,12,6,12.7,6,13.5v7C6,21.3,6.7,22,7.5,22S9,21.3,9,20.5v-7C9,12.7,8.3,12,7.5,12z"
      android:strokeColor="#A4c639"
      android:strokeWidth="0.5"
      android:trimPathEnd="1"/>

</vector>

2- Use RichPathView in your layout insead of ImageView :

<com.richpath.RichPathView
    android:id="@+id/richPathView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:vector="@drawable/vector_drawable" />

3- Animate all of your paths simultaneously.

RichPathView pathView = findViewById(R.id.richPathView);

RichPath[] paths = new RichPath[6];

for (int i = 0; i < paths.length; i++) {
    paths[i] = pathView.findRichPathByIndex(i);
}

RichPathAnimator
    .animate(paths)
    .trimPathEnd(0, 1)
    .duration(1600)
    .start();

also, it will be cleaner if we have an API like pathView.findAllRichPaths(), I have opened an issue for that here

Upvotes: 0

Arkay
Arkay

Reputation: 469

I found a library (here), which introduces a new imageview-esque view, which accepts vector drawables. You can then extract the paths (or any part of the vector drawable) either by name, or more importantly, by index. Thus this allows one to animate as many paths as you like by creating a for loop, such as

RichPathView view = findViewbyId(R.id.richpathview);
for(int i=0, i<100, i++){
    RichPath richPath = view.findRichPathByIndex(i);
                RichPathAnimator.animate(richPath)
                        .trimPathEnd(0, 1)
                        .duration(1000)
                        .start();
}

This block would "draw" the first 100 paths of a vector drawable simultaneously.

So this allows you to animate the parts of vector drawable, without having to explicitly name and reference every single part.

Upvotes: 0

Related Questions