Android ajoutant des animations simples tout en fixant la visibilité (view.Gone)

237

J'ai conçu une mise en page simple, j'ai terminé la conception sans animation, mais maintenant je veux ajouter des animations lors d'un événement click textview et je ne sais pas comment l'utiliser. Ma conception xml était-elle bonne ou non? Toute suggestion serait appréciée.

Mon 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>

Mon 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);
            }
        });

    }
}
arun
la source

Réponses:

706

Vous pouvez faire deux choses pour ajouter des animations, vous pouvez d'abord laisser Android animer les changements de disposition pour vous. De cette façon, chaque fois que vous modifiez quelque chose dans la mise en page, comme changer la visibilité de la vue ou les positions de la vue, Android créera automatiquement des animations de fondu / transition. Pour utiliser cet ensemble

android:animateLayoutChanges="true"

sur le nœud racine de votre mise en page.

Votre deuxième option serait d'ajouter manuellement des animations. Pour cela, je vous suggère d'utiliser la nouvelle API d'animation introduite dans Android 3.0 (Honeycomb). Je peux vous donner quelques exemples:

Cela s'estompe View:

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

Cela revient en arrière dans:

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

Cela déplace un Viewvers le bas de sa hauteur:

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

Cela ramène le Viewà sa position de départ après l'avoir déplacé ailleurs:

view.animate().translationY(0);

Vous pouvez également utiliser setDuration()pour définir la durée de l'animation. Par exemple, cela s'estompe Viewsur une période de 2 secondes:

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

Et vous pouvez combiner autant d'animations que vous le souhaitez, par exemple, cela se fane Viewet se déplace vers le bas en même temps sur une période de 0,3 seconde:

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

Et vous pouvez également affecter un auditeur à l'animation et réagir à toutes sortes d'événements. Comme quand l'animation démarre, quand elle se termine ou se répète, etc. En utilisant la classe abstraite, AnimatorListenerAdaptervous n'avez pas à implémenter tous les rappels AnimatorListenerà la fois, mais seulement ceux dont vous avez besoin. Cela rend le code plus lisible. Par exemple, le code suivant s'estompe et le Viewdéplace vers le bas de sa hauteur sur une période de 0,3 seconde (300 millisecondes) et lorsque l'animation est terminée, sa visibilité est définie sur 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);
            }
        });
Xaver Kapeller
la source
6
@Natix Je n'appellerais pas ce super appel redondant. Ne faites pas de modifications superficielles, il n'y a rien de mal.
Xaver Kapeller
5
Est-ce bien mais l'inverse ne fonctionne pas correctement pourquoi? view.setVisibility (View.VISIBLE); AVEC alpha (1.0f), apparaissent avec 100 rembourrage en haut ...
livrez
15
Doit effacer l'animation avant de définir la visibilité >> view.clearAnimation(); view.setVisibility(View.GONE);sinon la mise en page restera invisible et ne disparaîtra pas.
Eftekhari
2
@Eftekhari Ils ne sont pas du tout gourmands en ressources. Et si vous avez une version Android à jour, mais que vous avez toujours du retard, vous avez probablement un téléphone plus ancien avec une mémoire insuffisante ou une mauvaise puce graphique. Et je ne parle pas d'une nouvelle bibliothèque. Les animateurs sont natifs. Ils font partie du framework Android. Ils ont été lancés il y a 5 ans et aujourd'hui 97,9% de tous les appareils les prennent en charge. Il n'y a aucune raison de ne pas utiliser Animators ou au moins ViewCompat.animate()qui fait partie de la bibliothèque de support et utilise Animators sur les versions plus récentes et View Animations sur Android 3.0 et versions antérieures.
Xaver Kapeller
1
Mais lorsque 97,9% de tous les appareils sont Android 4.0 et plus, il ne reste plus grand-chose à faire ViewCompat.animate().
Xaver Kapeller
70

La manière la plus simple d'animer les Visibilitymodifications est d'utiliser Transition APIcelle disponible dans le package de support (androidx). Appelez simplement la TransitionManager.beginDelayedTransitionméthode, puis changez la visibilité de la vue. Il y a plusieurs transitions par défaut comme 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);
}

parentest le parent ViewGroupde la vue animée. Résultat:

entrez la description de l'image ici

Voici le résultat avec Slidetransition:

import androidx.transition.Slide;

Transition transition = new Slide(Gravity.BOTTOM);

entrez la description de l'image ici

Il est facile d'écrire une transition personnalisée si vous avez besoin de quelque chose de différent. Voici un exemple avec CircularRevealTransitionlequel j'ai écrit dans une autre réponse . Il affiche et masque la vue avec l'animation CircularReveal.

Transition transition = new CircularRevealTransition();

entrez la description de l'image ici

android:animateLayoutChanges="true"L'option fait la même chose, elle utilise simplement la transition automatique comme transition.

ashakirov
la source
@TouhidulIslam no. Ces classes sont disponibles dans le package androidx. Tout est rétrocompatible
ashakirov
2
Qu'en est-il de l'extension / de la réduction d'un groupe de vues?
TheRealChx101
Pouvez-vous faire plusieurs beginDelayedTransitions?
Jeongbebs
26

Veuillez vérifier ce lien. Ce qui permettra des animations comme les animations L2R, R2L, T2B, B2T.

Ce code montre l'animation de gauche à droite

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

si vous voulez le faire à partir de R2L, utilisez

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

de haut en bas comme

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

et vice versa ..

NullPointerException
la source
8
Cela déplace la vue de sa position d'origine.
Relm
24

Essayez d'ajouter cette ligne à la disposition parent xml

 android:animateLayoutChanges="true"

Votre mise en page ressemblera à ceci

<?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>
Ricardo Romo
la source
cela a fonctionné pour moi. Ma configuration utilise une disposition de contraintes comme vue racine. Lorsque la vue est définie sur View.VISIBLE, l'animation est affichée
EdgeDev
solution très simple et élégante
Naveed Ahmad
11

Sur la base de la réponse de @Xaver Kapeller, j'ai trouvé un moyen de créer une animation de défilement lorsque de nouvelles vues apparaissent à l'écran (et également une animation pour les masquer).

Cela va de cet état:

  • Bouton
  • Dernier bouton

à

  • Bouton
  • Bouton 1
  • Bouton 2
  • Bouton 3
  • Bouton 4
  • Dernier bouton

et vice versa.

Ainsi, lorsque l'utilisateur clique sur le premier bouton, les éléments "Button 1", "Button 2", "Button 3" et "Button 4" apparaîtront en utilisant une animation de fondu et l'élément "Last Button" descendra jusqu'à la fin. La hauteur de la disposition changera également, permettant d'utiliser correctement la vue de défilement.

Voici le code pour montrer les éléments avec animation:

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;
}

et voici le code pour cacher les éléments de l'animation:

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();
}

Notez qu'il existe un simple hack sur la méthode pour masquer l'animation. Sur l'écouteur d'animation mHiddenLinearLayout, j'ai dû supprimer l'écouteur lui-même en utilisant:

mHiddenLinearLayout.animate().setListener(null);

En effet, une fois qu'un écouteur d'animation est attaché à une vue, la prochaine fois qu'une animation est exécutée dans cette vue, l'écouteur sera également exécuté. Cela pourrait être un bogue dans l'écouteur d'animation.

Le code source du projet est sur GitHub: https://github.com/jiahaoliuliu/ViewsAnimated

Bon codage!

Mise à jour : pour tout écouteur attaché aux vues, il doit être supprimé une fois l'animation terminée. Cela se fait en utilisant

view.animate().setListener(null);
jiahao
la source
Celui-ci est la meilleure réponse
Naveen Kumar M
1
La view.animate().setListener(null);déclaration m'a sauvé la journée. Cela semble définitivement être un bug.
Michal Vician
@MichalVician Heureux que ce soit le cas!
jiahao
8

J'ai pu afficher / masquer un menu de cette façon:

MenuView.java (étend 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);
                }
            });
}

La source

Nelson Almendra
la source