Androidがsetvisibility(view.Gone)中に単純なアニメーションを追加する


237

シンプルなレイアウトを設計しました。アニメーションなしでデザインを完成させましたが、textviewクリックイベントのアニメーションを追加したいのですが、使い方がわかりません。私のxmlデザインは良さそうでしたか?任意の提案をいただければ幸いです。

私のXML

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:longClickable="false"
    android:orientation="vertical"
    android:weightSum="16" >

<LinearLayout 
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#00DDA0"
    android:layout_weight="3" >
</LinearLayout>
 <TextView
        android:id="@+id/Information1"
        android:layout_width="match_parent"
        android:layout_height="1dp" 
        android:text="Child Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>

 <LinearLayout
     android:id="@+id/layout1"
     android:layout_width="fill_parent"
     android:layout_height="0dp"
     android:layout_weight="8.5"
     android:background="#BBBBBB"
     android:orientation="vertical" >

     <TextView
         android:id="@+id/textView1"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
 </LinearLayout>

  <TextView
        android:id="@+id/Information2"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Parent Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
  <LinearLayout 
          android:id="@+id/layout2"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView2"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
   <TextView
        android:id="@+id/Information3"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Siblings" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
   <LinearLayout 
          android:id="@+id/layout3"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView3"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
    <TextView
        android:id="@+id/Information4"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Teacher Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
    <LinearLayout 
          android:id="@+id/layout4"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView4"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
     <TextView
        android:id="@+id/Information5"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Grade Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
     <LinearLayout 
          android:id="@+id/layout5"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
     <TextView
         android:id="@+id/textView5"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" />
      </LinearLayout>
      <TextView
        android:id="@+id/Information6"
        android:layout_width="match_parent"
        android:layout_height="0dp" 
        android:text="Health Information" 
        android:background="#0390BE"
        android:layout_weight="0.75"
        android:textColor="#FFFFFF"
        android:layout_gravity="center|fill_horizontal"/>
      <LinearLayout 
          android:id="@+id/layout6"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:orientation="vertical"
    android:background="#BBBBBB"
    android:layout_weight="8.5" >
    <TextView
         android:id="@+id/textView5"
         android:layout_width="match_parent"
         android:layout_height="match_parent"        
         android:text="TextView" 
         android:layout_weight="8.5" />
      </LinearLayout>

</LinearLayout>

私のjava

public class Certify_Info extends Activity {

    private static TextView tv2,tv3,tv5,tv6,tv4,tv1;
    private static LinearLayout l1,l2,l3,l4,l5,l6;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_certify__info);

        tv1=(TextView) findViewById(R.id.Information1);
        tv2=(TextView) findViewById(R.id.Information2);
        tv3=(TextView) findViewById(R.id.Information3);
        tv4=(TextView) findViewById(R.id.Information4);
        tv5=(TextView) findViewById(R.id.Information5);
        tv6=(TextView) findViewById(R.id.Information6); 

        l1=(LinearLayout) findViewById(R.id.layout1);
        l2=(LinearLayout) findViewById(R.id.layout2);
        l3=(LinearLayout) findViewById(R.id.layout3);
        l4=(LinearLayout) findViewById(R.id.layout4);
        l5=(LinearLayout) findViewById(R.id.layout5);
        l6=(LinearLayout) findViewById(R.id.layout6); 

        l2.setVisibility(View.GONE);
        l3.setVisibility(View.GONE); 
        l4.setVisibility(View.GONE); 
        l5.setVisibility(View.GONE);
        l6.setVisibility(View.GONE);

        tv1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l1.setVisibility(View.VISIBLE);
            }
        });
        tv2.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l2.setVisibility(View.VISIBLE);
            }
        });
        tv3.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l3.setVisibility(View.VISIBLE);

            }
        });
        tv4.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.GONE);
                l4.setVisibility(View.VISIBLE); 
            }
        });
        tv5.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l6.setVisibility(View.GONE);
                l5.setVisibility(View.VISIBLE); 
            }
        });
        tv6.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                l1.setVisibility(View.GONE);
                l2.setVisibility(View.GONE);
                l3.setVisibility(View.GONE); 
                l4.setVisibility(View.GONE); 
                l5.setVisibility(View.GONE);
                l6.setVisibility(View.VISIBLE);
            }
        });

    }
}

回答:


706

アニメーションを追加するには、2つのことを行うことができます。最初に、Androidにレイアウトの変更をアニメーションさせることができます。そうすることで、ビューの表示設定やビューの位置を変更するなど、レイアウトで何かを変更するたびに、androidは自動的にフェード/トランジションアニメーションを作成します。そのセットを使用するには

android:animateLayoutChanges="true"

レイアウトのルートノード上。

2番目のオプションは、手動でアニメーションを追加することです。このため、Android 3.0(Honeycomb)で導入された新しいアニメーションAPIを使用することをお勧めします。いくつか例を挙げましょう。

これはフェードアウトしますView

view.animate().alpha(0.0f);

これはそれをフェードバックします:

view.animate().alpha(1.0f);

これはViewその高さで下に移動します:

view.animate().translationY(view.getHeight());

これは、View他の場所に移動された後、を開始位置に戻します。

view.animate().translationY(0);

を使用setDuration()して、アニメーションの継続時間を設定することもできます。たとえば、これViewは2秒間にわたってフェードアウトします。

view.animate().alpha(0.0f).setDuration(2000);

そして、好きなだけ多くのアニメーションを組み合わせることができます。たとえば、これはa Viewをフェードアウトさせ、0.3秒の時間をかけて同時に下げます。

view.animate()
        .translationY(view.getHeight())
        .alpha(0.0f)
        .setDuration(300);

また、リスナーをアニメーションに割り当てて、あらゆる種類のイベントに反応することもできます。アニメーションの開始時、終了時、または繰り返し時などです。抽象クラスAnimatorListenerAdapterを使用することでAnimatorListener、一度にすべてのコールバックを実装する必要はなく、必要なものだけを実装できます。これにより、コードが読みやすくなります。たとえば、次のコードはフェードアウトし、View0.3秒(300ミリ秒)の期間にわたって高さだけ下に移動しView.GONEます。アニメーションが完了すると、可視性はに設定されます。

view.animate()
        .translationY(view.getHeight())
        .alpha(0.0f)
        .setDuration(300)
        .setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                view.setVisibility(View.GONE);
            }
        });

6
@Natix私はそのスーパーコールを冗長とは呼びません。何も問題がないことの表面的な編集を行わないでください。
Xaver Kapeller

5
良いのですが、逆が正しく機能しないのはなぜですか?view.setVisibility(View.VISIBLE); WITH alpha(1.0f)、100個のパディングトップで表示...
2016年

15
可視性を設定する前にアニメーションをクリアする必要がありview.clearAnimation(); view.setVisibility(View.GONE);ます>> そうしないと、レイアウトは不可視のままで、消えません。
エフテカリ2016

2
@Eftekhari彼らはリソースをまったく消費しません。また、最新のAndroidバージョンを使用している場合でも、メモリが少ないか、グラフィックチップが不良な古いスマートフォンを使用している場合よりも遅れが生じる可能性があります。そして、私は新しいライブラリについて話しているのではありません。アニメーターはネイティブです。これらはAndroidフレームワークの一部です。それらは5年前にリリースされ、今日では全デバイスの97.9%がそれらをサポートしています。Animatorsを使用しない理由はなく、少なくともViewCompat.animate()サポートライブラリの一部であり、新しいバージョンではAnimatorsを使用し、Android 3.0以下ではView Animationsを使用します。
Xaver Kapeller

1
ただし、すべてのデバイスの97.9%がAndroid 4.0以降である場合、に使用するユースケースはほとんどありませんViewCompat.animate()
Xaver Kapeller

70

Visibility変更をアニメーション化する最も簡単な方法はTransition API、サポート(androidx)パッケージで利用可能なものを使用することです。TransitionManager.beginDelayedTransitionメソッドを呼び出して、ビューの可視性を変更するだけです。Fade、のようないくつかのデフォルト遷移がありますSlide

import androidx.transition.TransitionManager;
import androidx.transition.Transition;
import androidx.transition.Fade;

private void toggle() {
    Transition transition = new Fade();
    transition.setDuration(600);
    transition.addTarget(R.id.image);

    TransitionManager.beginDelayedTransition(parent, transition);
    image.setVisibility(show ? View.VISIBLE : View.GONE);
}

アニメーションビューのparentViewGroupはどこにありますか。結果:

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

これはSlide遷移の結果です:

import androidx.transition.Slide;

Transition transition = new Slide(Gravity.BOTTOM);

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

別の何かが必要な場合は、カスタム遷移を簡単に記述できます。CircularRevealTransitionこれは私が別の答えで書いた例です。CircularRevealアニメーションでビューの表示と非表示を切り替えます。

Transition transition = new CircularRevealTransition();

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

android:animateLayoutChanges="true"オプションは同じことを行い、トランジションとしてAutoTransitionを使用します。


@TouhidulIslamいいえ。このクラスはandroidxパッケージで利用できます。すべて下位互換性があります
ashakirov

2
ビューグループの展開/縮小についてはどうですか?
TheRealChx101

複数beginDelayedTransitionのを実行できますか?
ジョンベブス

26

こちらのリンクをご確認ください。L2R、R2L、T2B、B2Tアニメーションなどのアニメーションを許可します。

このコードは、左から右へのアニメーションを示しています

TranslateAnimation animate = new TranslateAnimation(0,view.getWidth(),0,0);
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
view.setVisibility(View.GONE);

R2Lから実行する場合は、

TranslateAnimation animate = new TranslateAnimation(0,-view.getWidth(),0,0);

上から下へ

TranslateAnimation animate = new TranslateAnimation(0,0,0,view.getHeight());

逆もまた同様です。


8
これにより、ビューが元の位置から移動します。
Relm

24

この行をxml親レイアウトに追加してみてください

 android:animateLayoutChanges="true"

レイアウトは次のようになります

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:longClickable="false"
    android:orientation="vertical"
    android:weightSum="16">

    .......other code here

    </LinearLayout>

これでうまくいきました。私のセットアップでは、ルートビューとして制約レイアウトを使用しています。ビューがView.VISIBLEに設定されている場合、アニメーションが表示されます
EdgeDev

非常にシンプルでエレガントなソリューション
Naveed Ahmad

11

@Xaver Kapellerの回答に基づいて、新しいビューが画面に表示されたときにスクロールアニメーション(およびそれらを非表示にするアニメーション)を作成する方法を見つけました。

それはこの状態から行きます:

  • ボタン
  • 最後のボタン

  • ボタン
  • ボタン1
  • ボタン2
  • ボタン3
  • ボタン4
  • 最後のボタン

およびその逆。

したがって、ユーザーが最初のボタンをクリックすると、要素「ボタン1」、「ボタン2」、「ボタン3」、「ボタン4」がフェードアニメーションを使用して表示され、要素「最後のボタン」が最後まで移動します。レイアウトの高さも変更されるため、スクロールビューを適切に使用できます。

これはアニメーションで要素を表示するコードです:

private void showElements() {
    // Precondition
    if (areElementsVisible()) {
        Log.w(TAG, "The view is already visible. Nothing to do here");
        return;
    }

    // Animate the hidden linear layout as visible and set
    // the alpha as 0.0. Otherwise the animation won't be shown
    mHiddenLinearLayout.setVisibility(View.VISIBLE);
    mHiddenLinearLayout.setAlpha(0.0f);
    mHiddenLinearLayout
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .alpha(1.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    updateShowElementsButton();
                    mHiddenLinearLayout.animate().setListener(null);
                }
            })
    ;

    mLastButton
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .translationY(mHiddenLinearLayoutHeight);

    // Update the high of all the elements relativeLayout
    LayoutParams layoutParams = mAllElementsRelativeLayout.getLayoutParams();

    // TODO: Add vertical margins
    layoutParams.height = mLastButton.getHeight() + mHiddenLinearLayoutHeight;
}

これはアニメーションの要素を非表示にするコードです:

private void hideElements() {
    // Precondition
    if (!areElementsVisible()) {
        Log.w(TAG, "The view is already non-visible. Nothing to do here");
        return;
    }

    // Animate the hidden linear layout as visible and set
    mHiddenLinearLayout
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .alpha(0.0f)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    Log.v(TAG, "Animation ended. Set the view as gone");
                    super.onAnimationEnd(animation);
                    mHiddenLinearLayout.setVisibility(View.GONE);
                    // Hack: Remove the listener. So it won't be executed when
                    // any other animation on this view is executed
                    mHiddenLinearLayout.animate().setListener(null);
                    updateShowElementsButton();
                }
            })
    ;

    mLastButton
            .animate()
            .setDuration(ANIMATION_TRANSITION_TIME)
            .translationY(0);

    // Update the high of all the elements relativeLayout
    LayoutParams layoutParams = mAllElementsRelativeLayout.getLayoutParams();

    // TODO: Add vertical margins
    layoutParams.height = mLastButton.getHeight();
}

アニメーションを非表示にするメソッドに簡単なハックがあることに注意してください。アニメーションリスナーmHiddenLinearLayoutでは、次のものを使用してリスナー自体を削除する必要がありました。

mHiddenLinearLayout.animate().setListener(null);

これは、アニメーションリスナーがビューにアタッチされると、次にこのビューでアニメーションが実行されるときにリスナーも実行されるためです。これはアニメーションリスナーのバグの可能性があります。

プロジェクトのソースコードはGitHubにあります:https : //github.com/jiahaoliuliu/ViewsAnimated

幸せなコーディング!

更新:ビューに接続されているリスナーの場合、アニメーションの終了後に削除する必要があります。これは、

view.animate().setListener(null);

これが最良の答えです
Naveen Kumar M

1
そのview.animate().setListener(null);声明は私の一日を救った。これは間違いなくバグのようです。
Michal Vician 2017

@MichalVicianうれしかった!
ジアハオ2017

8

この方法でメニューを表示/非表示にすることができました:

MenuView.java(FrameLayoutを拡張)

private final int ANIMATION_DURATION = 500;

public void showMenu()
{
    setVisibility(View.VISIBLE);
    animate()
            .alpha(1f)
            .setDuration(ANIMATION_DURATION)
            .setListener(null);
}

private void hideMenu()
{
    animate()
            .alpha(0f)
            .setDuration(ANIMATION_DURATION)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    setVisibility(View.GONE);
                }
            });
}

ソース

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.