フラグメント間の遷移をアニメーション化する


284

フラグメント間の遷移をアニメーション化しようとしています。次のAndroidフラグメントとアニメーションから答えを得ました

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

DetailsFragment newFragment = DetailsFragment.newInstance();

ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");

// Start the animated transition.
ft.commit();

そして、私のR.anim.slide_in_left

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
       <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

しかし、私がこれを試したとき、それは示しました

02-08 16:27:37.961: ERROR/AndroidRuntime(1717): FATAL EXCEPTION: main
02-08 16:27:37.961: ERROR/AndroidRuntime(1717): java.lang.RuntimeException: Unknown animator name: translate
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:129)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:126)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:93)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:72)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.loadAnimator(FragmentManager.java:621)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:733)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:919)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.BackStackRecord.run(BackStackRecord.java:578)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1217)

何か案は?Honeycomb APIリファレンスを確認したところ、translateそこにあります。私は何を取りこぼしたか?
フラグメント間の遷移をアニメーション化する他の方法はありますか?ありがとうございました


アニメーションではなく、アニメーションを使用してください!android.R.ANIMATOR.fade_inは機能しますが、android.R.ANIM.fade_inは使用しないでください-動作がありますバグ
user1269737

回答:


347

あなたは、新しい使用する必要があるandroid.animationとフレームワーク(オブジェクトアニメーターを)FragmentTransaction.setCustomAnimationsなどFragmentTransaction.setTransition

setCustomAnimationsApiDemosのFragmentHideShow.javaからの使用例を次に示します。

ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

そして、これがres / animator / fade_in.xmlからの関連するアニメーターXML です

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/accelerate_quad"
    android:valueFrom="0"
    android:valueTo="1"
    android:propertyName="alpha"
    android:duration="@android:integer/config_mediumAnimTime" />

<set>以前のアニメーションフレームワークと同じように、を使用して複数のアニメーターを組み合わせることができます。


編集:人々はスライドイン/スライドアウトについて質問しているので、ここでコメントします。

スライドインとスライドアウト

あなたはもちろんアニメーション化することができtranslationXtranslationYx、およびyプロパティを、一般的にスライドすると画面外からのコンテンツをアニメーション伴います。私の知る限り、相対値を使用する遷移プロパティはありません。ただし、これはあなたが自分で書くことを妨げるものではありません。プロパティアニメーションでは、アニメーション化するオブジェクト(この場合はビュー)にゲッターメソッドとセッターメソッドが必要なだけなので、次のようにビューサブクラスで独自の メソッドgetXFractionsetXFractionメソッドを作成できます

public class MyFrameLayout extends FrameLayout {
    ...
    public float getXFraction() {
        return getX() / getWidth(); // TODO: guard divide-by-zero
    }

    public void setXFraction(float xFraction) {
        // TODO: cache width
        final int width = getWidth();
        setX((width > 0) ? (xFraction * width) : -9999);
    }
    ...
}

これで、「xFraction」プロパティを次のようにアニメーション化できます。

res / animator / slide_in.xml

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:valueFrom="-1.0"
    android:valueTo="0"
    android:propertyName="xFraction"
    android:duration="@android:integer/config_mediumAnimTime" />

アニメートしているオブジェクトの幅が親と同じでない場合は、見た目が正しくないため、ユースケースに合わせてプロパティの実装を微調整する必要がある場合があります。


8
fade_inとfade_outを機能させましたが、/ res / animator内の他のものはエラーを出します。そして、それらのどれも、スライドインとスライドアウトのためのものではないように見えます。これを行うために独自のxmlを作成しようとしましたが、結局のところ、フラグメントの上にフラグメントがあります。さらに助けてください?
Dave MacLean、2011

そして、翻訳はどうですか?XMLで定義されたobjectAnimatorのパーセンテージで値を変換するにはどうすればよいですか?xmlで定義された垂直スライドアニメーションでフリップするときに、AdapterViewFlipperをアニメーション化できませんでした...
GBouerat

6
11-19 10:27:50.912:W / PropertyValuesHolder(23107):タイプfloatのメソッドsetXFraction()がターゲットクラスクラスandroid.widget.FrameLayoutで見つかりません。しかし、私のXMLにはカスタムビューMyFrameLayoutがあります。何か案は?
12

13
実際には、ローマ、アドバイスはあまりにも他の道を行く必要があります:サポートライブラリを使用するときは、FragmentTransaction.setCustomAnimations AO古いアニメーションフレームワーク(android.R.anim)を使用する必要があります
PJV

1
@RomanNurikこの回答はほとんどのデバイスで問題なく機能しましたが、一部のユーザー(特に一部のSamsung Galaxy S3 / 4スマートフォン)では、何らかの理由でアニメーション中に幅が報告されず、フラグメントが表示されませんでした。ここに示すように、OnPredrawListenerを使用するユーザーのために機能させることができました:mavyasoni9891.blogspot.com/2014/06/…– ajpolt 2014
14:43

188

私はこのようにしました:

このメソッドを追加して、フラグメントアニメーション置き換えます

public void replaceFragmentWithAnimation(android.support.v4.app.Fragment fragment, String tag){
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
    transaction.replace(R.id.fragment_container, fragment);
    transaction.addToBackStack(tag);
    transaction.commit();
}

あなたはする必要が追加 4つのアニメーションをしてアニメーションでフォルダ仲間リソース

enter_from_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="-100%" android:toXDelta="0%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700"/>
</set>

exit_to_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="0%" android:toXDelta="100%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700" />
</set>

enter_from_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="100%" android:toXDelta="0%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700" />
</set>

exit_to_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="0%" android:toXDelta="-100%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700"/>
</set>

出力:

ここに画像の説明を入力してください

その完了


14
素晴らしいソリューション。ただし、RTLへの指示を交換した理由はわかりません。私の方法:.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right)
2016年

2
素晴らしいソリューション。アクティビティ間の移行には、同様のアプローチと同じアニメーションファイルが機能します。
2016

1
@MikeZriel、RES - >アニメーション- >ここにあなたのXMLを置く
Hirenパテル

3
おかげでHiren、私ははるかに優れた、よりiOSのように(300)への速度(700)を変更
マイク・Zriel

3
笑、私は解決策で戻ってきました。各Javaクラスにandroid.app.fragmentとFragmentManagerをインポートしていました。いくつかの資料を確認したところ、「setCustomAnimations()」を使用するにはandroid.support.v4ライブラリをインポートする必要があることがわかりました。それが 'support.v4.app'であることを言うことが重要です!すべてのメソッド「getFragmentManager()」を「getSupportFragmentManager()」に置き換え、すべてのインポート「android.app.Fragment / FragmentManager ...」を「android.support.v4.app ....」に置き換えた後、これをアニメーションはクラッシュせずにうまく機能し始めました...もしあなたが同様のケースで行き詰まっているなら、私の解決策を読んでください。Thx Hiren Patel xD
KoreanXcodeWorker 2017

58

Lollipop以降に自分を結びつける余裕があるなら、これはトリックをするようです:

import android.transition.Slide;
import android.util.Log;
import android.view.Gravity;
.
.
.
f = new MyFragment();
f.setEnterTransition(new Slide(Gravity.RIGHT));
f.setExitTransition(new Slide(Gravity.LEFT));
getFragmentManager()
    .beginTransaction()
    .replace(R.id.content, f, FRAG_TAG)  // FRAG_TAG is the tag for your fragment
    .commit();

お役に立てれば。


1
Lollipopでそれを実現することはできますが、Lollipopを実行しているデバイスの割合が無視できるほど小さいため(実際には、Androidデバイスの1.6%がLollipopを実行しています)、実用的ではありません。
Eran Goldin、2015

1
new Slide(...):呼び出しにはAPIレベル21が必要です
Chintan Soni、2015

getKey()は何を表していますか?
Alvaro 2016年

13
@EranGoldin永遠に続くものはありません。今日、Android 2.0以降のみのソリューションを非難しますか?
トム

@トムあなたはポイントがあります。ただし、アプリのユーザーベースが大きい場合、APIレベルを上げることはできません。ほとんどのユーザーがその後アプリを実行できなくなる場合、それはまったく解決策ではありません。
Eran Goldin

47

Nurikの答えは非常に有用だったが、私が見つけたまで、私は仕事にそれを得ることができませんでしたこれを。つまり、互換性ライブラリ(FragmentManagerではなくSupportFragmentManagerなど)を使用している場合、XMLアニメーションファイルの構文は異なります。


28

フラグメント間のスライドイン/アウトアニメーションは次のとおりです。

FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.animator.enter_anim, R.animator.exit_anim);
transaction.replace(R.id.listFragment, new YourFragment());
transaction.commit();

ここでは、objectAnimatorを使用しています。

アニメーターサブフォルダーにある2つのxmlファイルを次に示します。

enter_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
     <objectAnimator
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:duration="1000"
         android:propertyName="x"
         android:valueFrom="2000"
         android:valueTo="0"
         android:valueType="floatType" />
</set>

exit_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:propertyName="x"
        android:valueFrom="0"
        android:valueTo="-2000"
        android:valueType="floatType" />
</set>

私はそれが誰かを助けることを願っています。


37
ビューを2000ピクセル移動することは、非常に醜い解決策です。
carlo.marinangeli 2015

4
exit_animは画面から「ポップ」するだけで、画面全体にアニメーション表示されません。何か案は?私が使用しています.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right, R.animator.slide_in_left, R.animator.slide_out_right)
Pablo氏、

@MrPablo、その理由はおそらく上記のコードをコピーして貼り付けていないためです。setCustomAnimationsは、replaceメソッドの前に呼び出す必要があります。
Galya

この場合、他のフラグメントをアニメーションで置き換え、アニメーションのタイムアウトまたは継続時間の直前にアプリを最小化し、再びアプリケーションに戻ると、以前のフラグメントと現在のフラグメントが並行して表示されます。
プリンス

23

捕まった他の誰かのために、トランザクションの構築時にreplace / addの呼び出しの前にsetCustomAnimationsが呼び出されるようにしてください。


12

FragmentTransactionのAndroid SDK実装では、Animatorサポートライブラリがを必要Animationとしていますが、理由を聞かないでください。奇妙なコメントの後で、android 4.0.3コードとサポートライブラリを調べました。Android SDKの使用loadAnimator()とサポートライブラリの使用loadAnimation()


7

このシンプルで断食されたソリューションを使用してみてください。Androidにはデフォルトanimationのがいくつか用意されています。

fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentManager.addOnBackStackChangedListener(this);
fragmentTransaction.replace(R.id.frame, firstFragment, "h");
fragmentTransaction.addToBackStack("h");
fragmentTransaction.commit();

出力:

ここに画像の説明を入力してください


うわー..これは受け入れられる答えになるはずです!! シンプルでエレガントなソリューション。それは他の提案された回答と比較して非常にスムーズです
Chathura Buddhika
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.