6

svgs パスとアニメーション ベクトルを使用して、YouTube の再生/一時停止のようなアニメーションを実行しようとしています。

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クラッシュします:/

4

1 に答える 1

21

これを行うには、パスに互換性を持たせる必要があります。これを行うには複数の方法があります。実際のトランジションをどのように見せたいかに応じて、基本的にいくつかのトリックを使用してpathData、これら 2 つのドローアブルが同じ数と同じ種類のコマンドを同じ順序で持つようにします。この場合、1 つの三角形が 2 つの長方形と同じ形式のパスを使用して作成されることを意味します。

ここでの追加の問題は、三角形の場合、fillColor を使用しているため、画面に表示されるのは、描画したパス内で塗りつぶされたものですが、一時停止記号は太さ 1.0 の線を使用しているため、上に表示されるものです。画面は、図形で塗りつぶされるのではなく、実際には 2 本の太い線です。

これを変更して、両方とも色付きの太い線の代わりに 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 にあります。一時停止ボタンについては、以前は 2 行だけだったので、もう少し変更して、代わりに形状の輪郭を描きました。これを正しく表示するには、の<path>セクションを変更しdrawable/ic_pause_arrow.xmlて、play と同じように 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>

これで、モーフィングと互換性のある 2 つのベクター ドローアブルが作成されました。私は特にトランジションを試していないことに注意してください。希望どおりに見えない可能性があるため、少し実験が必要になる場合があります。私は自分のブログにチュートリアルを書きました。このチュートリアルは、ソース コードを含む問題やテクニックについての背景を説明しながら、より複雑な例をいくつか詳しく説明しています。お役に立てれば。

于 2015-11-16T18:16:19.290 に答える