Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Youtube Play/pause Animated Vector Drawable on android

I'm trying to do an animation like youtube Play/Pause with svgs paths and animated vector.

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();
      }
    });
  }
}

But I still get Caused by: android.view.InflateException: Binary XML file line #2 Can't morph from crash :/

like image 597
Daniel Gomez Rico Avatar asked Nov 16 '15 02:11

Daniel Gomez Rico


People also ask

How do you animate a drawable Android?

One way to animate Drawables is to load a series of Drawable resources one after another to create an animation. This is a traditional animation in the sense that it is created with a sequence of different images, played in order, like a roll of film. The AnimationDrawable class is the basis for Drawable animations.

Which type of animation resources are available in RES drawable directory?

There are two types of animations that you can do with the view animation framework: Tween animation: Creates an animation by performing a series of transformations on a single image with an Animation. Frame animation: or creates an animation by showing a sequence of images in order with an AnimationDrawable .


1 Answers

In order to do this, you need to make the paths compatible. There will be multiple ways to do this, depending on what you want the actual transition to look like, you basically use some tricks to make sure that the pathData of these two drawables have the same number and type of commands in the same order. In this case that means that one triangle is made using the same format of path as two rectangles.

An additional problem here is that in the case of the triangle you are using fillColor and so what you see on screen is what has been filled inside the path you draw, but the pause symbol is using lines with thickness 1.0, so what you see on screen are actually two thick lines rather than filled in shapes.

I suggest you should change this so that both use a fillColor instead of coloured, thick lines, then make the paths compatible.

Here's one example of how to make these compatible. Currently the incompatible paths look like this:

  <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>

These are not compatible because they do not have the same number of M & L commands or the same number of coordinates. Compatible paths would look like this:

  <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>

You should notice that these now have the same numbers of M and L commands with the same number of coordinates. I've added M12,0 L12,0 12,0 12,0 to the triangle's path; this part is not visible on screen as it doesn't really outline a shape, all of the points are at coordinate 12,0. For the pause button I've changed it a bit more since before it was just two lines, I've now outlined the shapes instead. For this to look right, change the <path> section of drawable/ic_pause_arrow.xml to use fillColor the same as the play one, so:

<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>

You should now have two vector drawables compatible for morphing. Note I haven't specifically tried out the transition, it may not look exactly like you want it to, so a bit of experimentation might be needed. I wrote a tutorial on my blog which I think is relevant where I detail some more complex examples of this, with more background about the issues and techniques including source code. Hope this helps.

like image 120
Lewis McGeary Avatar answered Nov 15 '22 06:11

Lewis McGeary