15

更新日:ソリューションが見つかりました!私の受け入れられた答えのためにスクロールダウン!Androids VectorDrawableアニメーションの正確な制御

1つの画像の複数の要素をアニメーション化して、ViewPagersの位置にアニメーションをリンクしたいとします(ドラッグされている現在のページに応じて、複数の要素がモーフィングまたは飛び入り/飛び出しています)。

アニメーションの現在のフレームを正確に制御する方法はありますか?たとえばのは、私はこのセットを持っていると仮定してみましょう:

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
    <objectAnimator 
     android:interpolator="@android:anim/decelerate_interpolator" 
     android:duration="800" 
     android:propertyName="scaleY" 
     android:valueFrom="0" 
     android:valueTo="1" /> 
    <objectAnimator 
     android:interpolator="@android:anim/decelerate_interpolator" 
     android:duration="800" 
     android:propertyName="scaleX" 
     android:valueFrom="0" 
     android:valueTo="1" /> 
    <objectAnimator 
     android:interpolator="@android:anim/decelerate_interpolator" 
     android:duration="800" 
     android:propertyName="rotation" 
     android:valueFrom="0" 
     android:valueTo="360" /> 
</set> 

アニメーションベクトルファイル:

ImageView mImage1 = (ImageView) findViewById(R.id.image_1); 
AnimatedVectorDrawableCompat animated = (AnimatedVectorDrawableCompat) mImage1.getDrawable(); 

animated.start(); 

のようなアニメーションを制御する方法はあります:アニメーションを実行するための

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" 
    android:drawable="@drawable/pre_signup_1" > 
    <target 
     android:name="plus_button" 
     android:animation="@anim/pre_signup_1_plus_container" /> 
    <target 
     android:name="plus" 
     android:animation="@anim/pre_signup_1_plus_sign" /> 
</animated-vector> 

JavaコードsetCurrentDuration(400)これはおそらくアニメーションの現在の状態を半分に設定しますか?そのベクトル描画可能オブジェクトをレイヤーに分割し、プログラムでアニメーション化する方法があるのでしょうか?前もって感謝します!

+0

@pskinkもっとコードを追加しました。どのように 'setCurrentFraction'幅のベクトルアニメーションを使うことができますか? – Arthur

答えて

7

VectorDrawableCompat内のパスとグループにアクセスし、必要に応じてアニメーション/モーフィングできます。 AndroidResourcesPathParserTypedArrayUtilsVectorDrawableCommonVectorDrawableCompat:私はandroid.support.graphics.drawableパッケージから次のクラスを複製することになったいくつかの研究の後

次に、VectorDrawableCompatクラスの内部で、次のメソッドとクラスをpublicにする必要があります。getTargetByName,VGroupVFullPath

次はVectorDrawableCompatクラスで、Androidバージョン(Build.VERSION.SDK_INT >= 23)を確認するブロックを削除します。理由はわかりませんが、それをしなければ、アニメーションはアンドロイドのAPI 23以降では機能しません(もっと研究が必要です)。

私はいくつかのプライベートメソッドを見逃しているかもしれませんが、問題に遭遇した場合にはそれらを公開するという問題です。

だから今私たちはVectorDrawableの層にアクセスできます!ここでViewPagerの位置に応じたベクトル群をスケーリングの小さな例です。

<?xml version="1.0" encoding="utf-8"?> 
<vector xmlns:android="http://schemas.android.com/apk/res/android" 
    android:width="276dp" 
    android:height="359dp" 
    android:viewportWidth="276" 
    android:viewportHeight="359"> 

    <group 
     android:pivotX="205.5" 
     android:pivotY="214.5" 
     android:name="my_group"> 
     <path 
      android:strokeColor="#4D394B" 
      android:strokeWidth="7" 
      android:strokeLineJoin="bevel" 
      android:fillColor="#1ED761" 
      android:pathData="M206.5,180 C186.9,180,171,195.9,171,215.5 S186.9,251,206.5,251 
C226.1,251,242,235.1,242,215.5 S226.1,180,206.5,180 Z" /> 
     <path 
      android:fillColor="#4D394B" 
      android:pathData="M210,211 L210,190 L202,190 L202,211 L181,211 L181,219 L202,219 L202,241 L210,241 
L210,219 L232,219 L232,211 Z" /> 
    </group> 
</vector> 

そして、これはグループをアニメーション化するために使用するコードです:

ImageView myImageView; 
VectorDrawableCompat.VGroup myVectorGroup; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_welcome); 

    myImageView = (ImageView) findViewById(R.id.image_1); 

    VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(getResources(), R.drawable.my_vector_drawable, null); 
    vectorDrawable.setAllowCaching(false); // Important to allow image updates 
    myVectorGroup = (VectorDrawableCompat.VGroup) vectorDrawable.getTargetByName("my_group"); 

    myImageView.setImageDrawable(vectorDrawable); 

    mViewPager = (ViewPager) findViewById(R.id.pager); 
    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 
     @Override 
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
      if(myVectorGroup != null && position < 1) { 
       myVectorGroup.setScaleX(1f - positionOffset); 
       myVectorGroup.setScaleY(1f - positionOffset); 

       myImageView.invalidate(); 
      } 
     } 
    }); 
} 

私が判断するために、いくつかのより多くのテストが必要互換性は、それは今のところ動作します!

+0

これはまだ試していませんが、素晴らしい仕事です。 AnimatedVectorDrawableがこの能力をボックスから外していることは残念です。 –

+0

ええ、それは私が言っていることです!私は現在の場所と実際に複雑なアニメーションでこの可能性を使用しています!古いデバイスでもかなり速いです! – Arthur

+0

@Arthur vectorDrawableの既存のコードを変更した後、パスデータを補間するコードはありません。あなたは、コードを共有して、あなたがどのように達成したかを明確に理解してください。前のロリポップデバイス、すなわちAPI 15の上で –

1

AnimatedVectorDrawablesのドキュメントでは、アニメーションの状態を追跡したり、animationStartやanimationEnd以外の状態にジャンプする方法はありません。

この効果を得るには、カスタムソリューションを使用する必要があります。 This blog postは、Androidのウィジェット状態のトラッキングを使用して同様の効果を得る方法について説明しています。

+0

オブジェクトを前後にアニメーション化するもう1つの方法がありますか?私はベクトルグループを意味するのではなく、 'ImageView'を分離するかもしれませんか? – Arthur

1

AnimatedVectorDrawable/AnimatedVectorDrawableCompatを使用してプログラムで行うことはできません。

回避策は、そのレベルLevel List drawableを使用してアニメーション化することです。 をしかし、あなたはスムーズな移行をシミュレートするためのレベルの画像の多くを必要とするだろう、私はデモのために、ここだけの三つのレベルを使用しています。レイアウトファイルに次にのres /描画可能/ my_level_list.xml

<?xml version="1.0" encoding="utf-8"?> 
<level-list xmlns:android="http://schemas.android.com/apk/res/android"> 
<item android:drawable="@drawable/level0" 
    android:maxLevel="0"/> 
    <item android:drawable="@drawable/level1" 
     android:maxLevel="1"/> 

    <item android:drawable="@drawable/level2" 
     android:maxLevel="2"/> 
</level-list> 

まずあなたは、このような描画可能なレベルのリストを定義します

<ImageView 
     android:id="@+id/img" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerInParent="true" 
     android:src="@drawable/my_level_list" /> 

次に、あなたの活動に:

int MIN_LEVEL=0; 
int MAX_LEVEL=2; 

ImageView img=(ImageView)findViewById(R.id.img); 

Drawable myLevelSetDrawable= img.getDrawable(); 
ObjectAnimator anim=ObjectAnimator.ofInt(myLevelSetDrawable,"level",MIN_LEVEL,MAX_LEVEL); 
anim.setInterpolator(new BounceInterpolator()); 
AnimatorSet set=new AnimatorSet(); 
set.play(anim); 
set.setDuration(1000); 
set.start(); 

希望します。

関連する問題