web-dev-qa-db-ja.com

Gmailの3フラグメントアニメーションシナリオの実用サンプルを完了しますか?

TL; DR:「Gmail 3フラグメントアニメーション」シナリオと呼ぶものの完全な作業サンプルを探しています。具体的には、次のような2つのフラグメントから始めます。

two fragments

UIイベント(フラグメントBの何かをタップするなど)が発生すると、次のようになります。

  • 画面の左側にスライドするフラグメントA
  • フラグメントBは、画面の左端にスライドし、フラグメントAによって空けられた場所を占めるように縮小します
  • フラグメントCは、画面の右側からスライドして、フラグメントBによって空いた場所を占有します。

そして、BACKボタンを押すと、その一連の操作が逆になります。

今、私は多くの部分的な実装を見てきました。それらのうちの4つを以下でレビュ​​ーします。不完全であることに加えて、彼らはすべて問題を抱えています。


@Reto Meierは、同じ基本的な質問に この一般的な回答 を提供し、FragmentTransactionsetCustomAnimations()を使用することを示しました。 2フラグメントシナリオの場合(たとえば、最初はフラグメントAのみが表示され、アニメーション効果を使用して新しいフラグメントBに置き換えたい場合)、私は完全に同意します。しかしながら:

  • 指定できるのは1つの「イン」アニメーションと1つの「アウト」アニメーションのみであるため、3つのフラグメントのシナリオに必要なすべての異なるアニメーションをどのように処理するかわかりません。
  • 彼のサンプルコードの_<objectAnimator>_は、ピクセル単位のハードワイヤード位置を使用しており、さまざまな画面サイズを考えると非現実的と思われますが、setCustomAnimations()はアニメーションリソースを必要とするため、 Java
  • スケールベースのオブジェクトアニメーターが、LinearLayoutのような_Android:layout_weight_のようなものとどのように結び付けられているかについて、私は途方に暮れています。
  • フラグメントCが最初にどのように処理されるかについて私は迷っています(GONE?_Android:layout_weight_ of _0_ ??スケール0に事前にアニメーション化されていますか?)

@Roman Nurikは、自分で定義したものも含めて、 任意のプロパティをアニメーション化できる と指摘しています。それは、独自のカスタムレイアウトマネージャーサブクラスを発明することを犠牲にして、配線された位置の問題を解決するのに役立ちます。これは一部の人には役立ちますが、私はまだRetoの残りのソリューションに困惑しています。


このPastebinエントリ の作成者は、基本的に3つのフラグメントすべてが最初にコンテナに存在し、最初はフラグメントCがhide()トランザクション操作を介して非表示になると言っている興味深いコードを示しています。 UIイベントが発生すると、show() Cとhide() Aを実行します。ただし、Bがサイズを変更するという事実をどのように処理するかはわかりません。また、明らかに複数のフラグメントを同じコンテナに追加できるという事実に依存しており、それが長期的に信頼できる動作であるかどうかはわかりません(もちろんfindFragmentById()私はそれと一緒に暮らすことができます)。


このブログ投稿 の作成者は、GmailがsetCustomAnimations()をまったく使用せず、代わりにオブジェクトアニメーターを直接使用することを示しています(「ルートビューの左マージンを変更し、右のビュー」)。ただし、これは依然として2フラグメントソリューションであるAFAICTであり、ここに示した実装では、ピクセル単位の寸法が再度配線されています。


私はこれでプラグインを続けますので、いつか自分で答えるかもしれませんが、誰かがこのアニメーションシナリオの3つのフラグメントソリューションを解決し、コード(またはそれへのリンク)を投稿できることを本当に望んでいます。 Androidのアニメーションは、私が私の髪を引っ張り出したいと思うようにします。そして、私を見たあなたの人々は、これがほとんど実りのない努力であることを知っています。

123
CommonsWare

OK、質問のコメントでの@Christopherの提案ごとに、Email AOSPアプリから派生した私自身のソリューションがあります。

https://github.com/commonsguy/cw-omnibus/tree/master/Animation/ThreePane

@weakwireのソリューションは私のものを思い起こさせますが、彼はアニメーターではなく古典的なAnimationを使用し、RelativeLayoutルールを使用してポジショニングを実施しています。報奨金の観点から、彼はおそらく報奨金を得るでしょう、他の誰かがよりスマートな解決策でまだ答えを投稿しない限り。


一言で言えば、そのプロジェクトのThreePaneLayoutLinearLayoutサブクラスであり、3人の子供がいる風景で動作するように設計されています。これらの子の幅は、任意の手段を使用してレイアウトXMLで設定できます。重みを使用して表示しますが、ディメンションリソースなどで特定の幅を設定できます。 3番目の子(質問のフラグメントC)の幅はゼロでなければなりません。

_package com.commonsware.Android.anim.threepane;

import Android.animation.Animator;
import Android.animation.AnimatorListenerAdapter;
import Android.animation.ObjectAnimator;
import Android.content.Context;
import Android.util.AttributeSet;
import Android.view.View;
import Android.widget.LinearLayout;

public class ThreePaneLayout extends LinearLayout {
  private static final int ANIM_DURATION=500;
  private View left=null;
  private View middle=null;
  private View right=null;
  private int leftWidth=-1;
  private int middleWidthNormal=-1;

  public ThreePaneLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    initSelf();
  }

  void initSelf() {
    setOrientation(HORIZONTAL);
  }

  @Override
  public void onFinishInflate() {
    super.onFinishInflate();

    left=getChildAt(0);
    middle=getChildAt(1);
    right=getChildAt(2);
  }

  public View getLeftView() {
    return(left);
  }

  public View getMiddleView() {
    return(middle);
  }

  public View getRightView() {
    return(right);
  }

  public void hideLeft() {
    if (leftWidth == -1) {
      leftWidth=left.getWidth();
      middleWidthNormal=middle.getWidth();
      resetWidget(left, leftWidth);
      resetWidget(middle, middleWidthNormal);
      resetWidget(right, middleWidthNormal);
      requestLayout();
    }

    translateWidgets(-1 * leftWidth, left, middle, right);

    ObjectAnimator.ofInt(this, "middleWidth", middleWidthNormal,
                         leftWidth).setDuration(ANIM_DURATION).start();
  }

  public void showLeft() {
    translateWidgets(leftWidth, left, middle, right);

    ObjectAnimator.ofInt(this, "middleWidth", leftWidth,
                         middleWidthNormal).setDuration(ANIM_DURATION)
                  .start();
  }

  public void setMiddleWidth(int value) {
    middle.getLayoutParams().width=value;
    requestLayout();
  }

  private void translateWidgets(int deltaX, View... views) {
    for (final View v : views) {
      v.setLayerType(View.LAYER_TYPE_HARDWARE, null);

      v.animate().translationXBy(deltaX).setDuration(ANIM_DURATION)
       .setListener(new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
           v.setLayerType(View.LAYER_TYPE_NONE, null);
         }
       });
    }
  }

  private void resetWidget(View v, int width) {
    LinearLayout.LayoutParams p=
        (LinearLayout.LayoutParams)v.getLayoutParams();

    p.width=width;
    p.weight=0;
  }
}
_

ただし、実行時に、幅を最初に設定した方法に関係なく、hideLeft()を初めて使用して質問がフラグメントAと呼ばれるものを表示するように切り替えたときに、幅管理がThreePaneLayoutに引き継がれます。およびBからフラグメントBおよびC。ThreePaneLayoutの用語では、フラグメントと特定の関係はありませんが、3つの部分はleftmiddle、およびrightです。 。 hideLeft()を呼び出すときに、leftおよびmiddleのサイズを記録し、3つのいずれかで使用された重みをゼロにするため、サイズを完全に制御できます。 。 hideLeft()の時点で、rightのサイズをmiddleの元のサイズに設定します。

アニメーションは2つあります。

  • ViewPropertyAnimatorを使用して、ハードウェア層を使用して、leftの幅で左に3つのウィジェットの変換を実行します
  • ObjectAnimatorのカスタム擬似プロパティでmiddleWidthを使用して、middleの幅を元の幅からleftの元の幅に変更します

(これは今のところ動作しますが、AnimatorSetObjectAnimatorsをこれらすべてに使用することをお勧めします)

middleWidthObjectAnimatorは、かなり連続した無効化を必要とするため、ハードウェア層の値を無効にすることも可能です)

間違いなくアニメーションの理解にまだギャップがあり、括弧で囲まれた文が好きな可能性があります)

最終的な効果は、leftが画面からスライドし、middleが元の位置とサイズのleftにスライドし、rightmiddleのすぐ後ろに移動することです。

showLeft()は、アニメーターの同じミックスを使用して、単に方向を逆にして、プロセスを単純に逆にします。

アクティビティは、ThreePaneLayoutを使用して、ListFragmentウィジェットとButtonのペアを保持します。左側のフラグメントで何かを選択すると、中央のフラグメントが追加(またはコンテンツの更新)されます。中央のフラグメントで何かを選択すると、Buttonのキャプションが設定され、ThreePaneLayouthideLeft()が実行されます。左側を非表示にした場合、BACKを押すと、showLeft();が実行されます。それ以外の場合、BACKはアクティビティを終了します。これは、アニメーションに影響を与えるためにFragmentTransactionsを使用しないため、その「バックスタック」を自分で管理することにこだわっています。

上記にリンクされているプロジェクトは、ネイティブフラグメントとネイティブアニメーターフレームワークを使用します。 Androidサポートフラグメントバックポートと NineOldAndroids をアニメーションに使用する同じプロジェクトの別のバージョンがあります。

https://github.com/commonsguy/cw-omnibus/tree/master/Animation/ThreePaneBC

バックポートは第1世代のKindle Fireで正常に機能しますが、ハードウェアの仕様が低く、ハードウェアアクセラレーションのサポートがないため、アニメーションは少しぎくしゃくしています。両方の実装は、Nexus 7およびその他の現行世代のタブレットではスムーズに見えます。

このソリューションを改善する方法や、ここでやったこと(または@weakwireで使用したもの)よりも明確な利点を提供する他のソリューションについては、私は確かにオープンです。

貢献してくれたすべての人に感謝します!

31
CommonsWare

github (すべてのAndroidバージョンで動作していますが、この種のアニメーションにはハードウェアアクセラレーションを表示することを強くお勧めします。より良くフィットするはずです)

アニメーションを含むデモビデオは ここ (スクリーンキャストの遅いフレームレートの原因です。実際のパフォーマンスは非常に高速です)


使用法:

_layout = new ThreeLayout(this, 3);
layout.setAnimationDuration(1000);
setContentView(layout);
layout.getLeftView();   //<---inflate FragmentA here
layout.getMiddleView(); //<---inflate FragmentB here
layout.getRightView();  //<---inflate FragmentC here

//Left Animation set
layout.startLeftAnimation();

//Right Animation set
layout.startRightAnimation();

//You can even set interpolators
_

説明

新しいカスタムRelativeLayout(ThreeLayout)と2つのカスタムアニメーション(MyScalAnimation、MyTranslateAnimation)を作成しました

ThreeLayoutは、他の表示ビューに_weight=1_があると仮定して、左ペインの重みをparamとして取得します。

したがって、new ThreeLayout(context,3)は、3つの子を持つ新しいビューと、画面全体の1/3を持つ左ペインを作成します。他のビューは、使用可能なすべてのスペースを占有します。

実行時に幅を計算します。より安全な実装は、draw()で最初に次元を計算することです。 post()の代わりに

アニメーションの拡大縮小と移動は、擬似[拡大縮小、移動]ではなく、実際にビューのサイズ変更と移動を行います。 fillAfter(true)はどこでも使用されていないことに注意してください。

View2はView1の権利です

そして

View3はView2の権利です

これらのルールを設定すると、RelativeLayoutは他のすべてを処理します。アニメーションは、スケールでmargins(移動中)および_[width,height]_を変更します

各子にアクセスするには(フラグメントでそれを膨らませるために、電話をかけることができます

_public FrameLayout getLeftLayout() {}

public FrameLayout getMiddleLayout() {}

public FrameLayout getRightLayout() {}
_

以下に2つのアニメーションを示します


Stage1

--- IN画面----------!----- OUT ----

[View1] [_____ View2 _____] [_____ View3_____]

Stage2

--OUT-!-------- IN画面------

[View1] [View2] [_____ View3_____]

66
weakwire

この問題を解決するPanesLibraryというライブラリを構築しました。以前に提供されていたものよりもさらに柔軟です:

  • 各ペインは動的にサイズ変更できます
  • 任意の数のペイン(2つまたは3つだけでなく)を使用できます
  • ペイン内のフラグメントは、向きを変更しても正しく保持されます。

こちらで確認できます: https://github.com/Mapsaurus/Android-PanesLibrary

デモは次のとおりです。 http://www.youtube.com/watch?v=UA-lAGVXoLU&feature=youtu.be

基本的に、任意の数の動的サイズのペインを簡単に追加し、それらのペインにフラグメントを添付できます。お役に立てば幸いです! :)

13
coda

リンクした例の1つを構築する( http://Android.amberfog.com/?p=758 )、layout_weightプロパティ?この方法で、3つのフラグメントの重みの変化を一緒にアニメーション化でき、それらがすべてうまくスライドするというボーナスが得られます。

シンプルなレイアウトから始めます。 layout_weight、3つのパネルのルートビューとしてLinearLayoutが必要です。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/container"
Android:orientation="horizontal"
Android:layout_width="match_parent"
Android:layout_height="match_parent">

<LinearLayout
    Android:id="@+id/panel1"
    Android:layout_width="0dip"
    Android:layout_weight="1"
    Android:layout_height="match_parent"/>

<LinearLayout
    Android:id="@+id/panel2"
    Android:layout_width="0dip"
    Android:layout_weight="2"
    Android:layout_height="match_parent"/>

<LinearLayout
    Android:id="@+id/panel3"
    Android:layout_width="0dip"
    Android:layout_weight="0"
    Android:layout_height="match_parent"/>
</LinearLayout>

次に、デモクラス:

public class DemoActivity extends Activity implements View.OnClickListener {
    public static final int ANIM_DURATION = 500;
    private static final Interpolator interpolator = new DecelerateInterpolator();

    boolean isCollapsed = false;

    private Fragment frag1, frag2, frag3;
    private ViewGroup panel1, panel2, panel3;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        panel1 = (ViewGroup) findViewById(R.id.panel1);
        panel2 = (ViewGroup) findViewById(R.id.panel2);
        panel3 = (ViewGroup) findViewById(R.id.panel3);

        frag1 = new ColorFrag(Color.BLUE);
        frag2 = new InfoFrag();
        frag3 = new ColorFrag(Color.RED);

        final FragmentManager fm = getFragmentManager();
        final FragmentTransaction trans = fm.beginTransaction();

        trans.replace(R.id.panel1, frag1);
        trans.replace(R.id.panel2, frag2);
        trans.replace(R.id.panel3, frag3);

        trans.commit();
    }

    @Override
    public void onClick(View view) {
        toggleCollapseState();
    }

    private void toggleCollapseState() {
        //Most of the magic here can be attributed to: http://Android.amberfog.com/?p=758

        if (isCollapsed) {
            PropertyValuesHolder[] arrayOfPropertyValuesHolder = new PropertyValuesHolder[3];
            arrayOfPropertyValuesHolder[0] = PropertyValuesHolder.ofFloat("Panel1Weight", 0.0f, 1.0f);
            arrayOfPropertyValuesHolder[1] = PropertyValuesHolder.ofFloat("Panel2Weight", 1.0f, 2.0f);
            arrayOfPropertyValuesHolder[2] = PropertyValuesHolder.ofFloat("Panel3Weight", 2.0f, 0.0f);
            ObjectAnimator localObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(this, arrayOfPropertyValuesHolder).setDuration(ANIM_DURATION);
            localObjectAnimator.setInterpolator(interpolator);
            localObjectAnimator.start();
        } else {
            PropertyValuesHolder[] arrayOfPropertyValuesHolder = new PropertyValuesHolder[3];
            arrayOfPropertyValuesHolder[0] = PropertyValuesHolder.ofFloat("Panel1Weight", 1.0f, 0.0f);
            arrayOfPropertyValuesHolder[1] = PropertyValuesHolder.ofFloat("Panel2Weight", 2.0f, 1.0f);
            arrayOfPropertyValuesHolder[2] = PropertyValuesHolder.ofFloat("Panel3Weight", 0.0f, 2.0f);
            ObjectAnimator localObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(this, arrayOfPropertyValuesHolder).setDuration(ANIM_DURATION);
            localObjectAnimator.setInterpolator(interpolator);
            localObjectAnimator.start();
        }
        isCollapsed = !isCollapsed;
    }

    @Override
    public void onBackPressed() {
        //TODO: Very basic stack handling. Would probably want to do something relating to fragments here..
        if(isCollapsed) {
            toggleCollapseState();
        } else {
            super.onBackPressed();
        }
    }

    /*
     * Our magic getters/setters below!
     */

    public float getPanel1Weight() {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)     panel1.getLayoutParams();
        return params.weight;
    }

    public void setPanel1Weight(float newWeight) {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel1.getLayoutParams();
        params.weight = newWeight;
        panel1.setLayoutParams(params);
    }

    public float getPanel2Weight() {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel2.getLayoutParams();
        return params.weight;
    }

    public void setPanel2Weight(float newWeight) {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel2.getLayoutParams();
        params.weight = newWeight;
        panel2.setLayoutParams(params);
    }

    public float getPanel3Weight() {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel3.getLayoutParams();
        return params.weight;
    }

    public void setPanel3Weight(float newWeight) {
        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panel3.getLayoutParams();
        params.weight = newWeight;
        panel3.setLayoutParams(params);
    }


    /**
     * Crappy fragment which displays a toggle button
     */
    public static class InfoFrag extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle     savedInstanceState) {
            LinearLayout layout = new LinearLayout(getActivity());
            layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            layout.setBackgroundColor(Color.DKGRAY);

            Button b = new Button(getActivity());
            b.setOnClickListener((DemoActivity) getActivity());
            b.setText("Toggle Me!");

            layout.addView(b);

            return layout;
        }
    }

    /**
     * Crappy fragment which just fills the screen with a color
     */
    public static class ColorFrag extends Fragment {
        private int mColor;

        public ColorFrag() {
            mColor = Color.BLUE; //Default
        }

        public ColorFrag(int color) {
            mColor = color;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            FrameLayout layout = new FrameLayout(getActivity());
            layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));

            layout.setBackgroundColor(mColor);
            return layout;
        }
    }
}

また、この例ではFragmentTransactionsを使用してアニメーションを実現していません(むしろ、フラグメントがアタッチされているビューをアニメーション化します)。したがって、すべてのバックスタック/フラグメントトランザクションを自分で行う必要があります。うまく、これは悪いトレードオフのようには見えません:)

動作中の恐ろしい低解像度ビデオ: http://youtu.be/Zm517j3bFCo

6
DanielGrech

これはフラグメントを使用していません。3つの子を持つカスタムレイアウトです。メッセージをクリックすると、offsetLeftAndRight()とアニメーターを使用して3つの子をオフセットします。

JellyBeanでは、[開発者オプション]設定で[レイアウト境界の表示]を有効にできます。スライドアニメーションが完了すると、左側のメニューがまだ中央パネルの下にあることがわかります。

Cyril MottierのFly-inアプリメニュー に似ていますが、2ではなく3つの要素があります。

さらに、3番目の子のViewPagerは、この動作の別の指標です。通常、ViewPagerはフラグメントを使用します(必要がないことはわかっていますが、Fragment)、および別のFragments内でFragmentを使用できないため、3つの子はおそらくフラグメントではありません。

5

私は現在、そのようなことをしようとしていますが、フラグメントBスケールは利用可能なスペースを取り、十分なスペースがある場合は3ペインを同時に開くことができます。ここに私の解決策がありますが、私はそれを固守するつもりかどうかはわかりません。誰かが正しい道を示す答えを提供してくれることを願っています。

LinearLayoutを使用してウェイトをアニメートする代わりに、RelativeLayoutを使用してマージンをアニメートします。更新のたびにrequestLayout()を呼び出す必要があるため、最善の方法であるかどうかはわかりません。しかし、私のすべてのデバイスでスムーズです。

だから、私はレイアウトをアニメーション化し、フラグメントトランザクションを使用していません。フラグメントCが開いている場合は、戻るボタンを手動で処理して閉じます。

FragmentBは、layout_toLeftOf/ToRightOfを使用して、フラグメントAとCに揃えて保持します。

アプリがフラグメントCを表示するイベントをトリガーすると、フラグメントCをスライドインし、同時にフラグメントAをスライドアウトします。 (2つの個別のアニメーション)。逆に、フラグメントAが開くと、同時にCを閉じます。

ポートレートモードまたは小さな画面では、わずかに異なるレイアウトを使用し、画面上でフラグメントCをスライドします。

フラグメントAおよびCの幅にパーセンテージを使用するには、実行時に計算する必要があると思います...(?)

アクティビティのレイアウトは次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/rootpane"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent">

    <!-- FRAGMENT A -->
    <fragment
        Android:id="@+id/fragment_A"
        Android:layout_width="300dp"
        Android:layout_height="fill_parent"
        class="com.xyz.fragA" />

    <!-- FRAGMENT C -->
    <fragment
        Android:id="@+id/fragment_C"
        Android:layout_width="600dp"
        Android:layout_height="match_parent"
        Android:layout_alignParentRight="true"
        class="com.xyz.fragC"/>

    <!-- FRAGMENT B -->
    <fragment
        Android:id="@+id/fragment_B"
        Android:layout_width="match_parent"
        Android:layout_height="fill_parent"
        Android:layout_marginLeft="0dip"
        Android:layout_marginRight="0dip"
        Android:layout_toLeftOf="@id/fragment_C"
        Android:layout_toRightOf="@id/fragment_A"
        class="com.xyz.fragB" />

</RelativeLayout>

FragmentCをスライドインまたはスライドアウトするアニメーション:

private ValueAnimator createFragmentCAnimation(final View fragmentCRootView, boolean slideIn) {

    ValueAnimator anim = null;

    final RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) fragmentCRootView.getLayoutParams();
    if (slideIn) {
        // set the rightMargin so the view is just outside the right Edge of the screen.
        lp.rightMargin = -(lp.width);
        // the view's visibility was GONE, make it VISIBLE
        fragmentCRootView.setVisibility(View.VISIBLE);
        anim = ValueAnimator.ofInt(lp.rightMargin, 0);
    } else
        // slide out: animate rightMargin until the view is outside the screen
        anim = ValueAnimator.ofInt(0, -(lp.width));

    anim.setInterpolator(new DecelerateInterpolator(5));
    anim.setDuration(300);
    anim.addUpdateListener(new AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Integer rightMargin = (Integer) animation.getAnimatedValue();
            lp.rightMargin = rightMargin;
            fragmentCRootView.requestLayout();
        }
    });

    if (!slideIn) {
        // if the view was sliding out, set visibility to GONE once the animation is done
        anim.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationEnd(Animator animation) {
                fragmentCRootView.setVisibility(View.GONE);
            }
        });
    }
    return anim;
}
2
boblebel