web-dev-qa-db-fra.com

Comment réaliser une animation d'agrandissement / repli fluide

Je fais référence au code d'animation expand/collapse trouvé ici.

Android: animation de développement/réduction

Bien que cela fonctionne, il ne fait pas bien le travail. L'animation n'est pas fluide.

Je me connecte au code.

public static void expand(final View v) {
    v.measure(MeasureSpec.makeMeasureSpec(((View)v.getParent()).getWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(1024, MeasureSpec.AT_MOST));
    final int targtetHeight = v.getMeasuredHeight();

    v.getLayoutParams().height = 0;
    v.setVisibility(View.VISIBLE);
    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            v.getLayoutParams().height = interpolatedTime == 1
                    ? LayoutParams.WRAP_CONTENT
                    : (int)(targtetHeight * interpolatedTime);
            Log.i("CHEOK", "E v.getLayoutParams().height = " + v.getLayoutParams().height);
            v.requestLayout();
        }

Le message de journal suivant est imprimé.

10-09 12:29:58.808: I/CHEOK(7874): E v.getLayoutParams().height = 0
10-09 12:29:58.808: I/CHEOK(7874): E v.getLayoutParams().height = 0
10-09 12:29:58.918: I/CHEOK(7874): E v.getLayoutParams().height = 11
10-09 12:29:59.015: I/CHEOK(7874): E v.getLayoutParams().height = 35
10-09 12:29:59.117: I/CHEOK(7874): E v.getLayoutParams().height = 64
10-09 12:29:59.215: I/CHEOK(7874): E v.getLayoutParams().height = 85
10-09 12:29:59.316: I/CHEOK(7874): E v.getLayoutParams().height = -2
10-09 12:29:59.406: I/CHEOK(7874): E v.getLayoutParams().height = -2

Une nouvelle hauteur se produit toutes les ~ 100 ms. Ainsi, le FPS de l'animation est d'environ 10fps

Je veux voir quelle est la fréquence d'images d'animation idéale. Je supprime la v.requestLayout();. J'obtiens la journalisation suivante.

10-09 12:32:06.547: I/CHEOK(8926): E v.getLayoutParams().height = 0
10-09 12:32:06.562: I/CHEOK(8926): E v.getLayoutParams().height = 0
10-09 12:32:06.605: I/CHEOK(8926): E v.getLayoutParams().height = 4
10-09 12:32:06.625: I/CHEOK(8926): E v.getLayoutParams().height = 7
10-09 12:32:06.644: I/CHEOK(8926): E v.getLayoutParams().height = 10
10-09 12:32:06.664: I/CHEOK(8926): E v.getLayoutParams().height = 14
10-09 12:32:06.679: I/CHEOK(8926): E v.getLayoutParams().height = 18
10-09 12:32:06.699: I/CHEOK(8926): E v.getLayoutParams().height = 22
10-09 12:32:06.715: I/CHEOK(8926): E v.getLayoutParams().height = 27
10-09 12:32:06.734: I/CHEOK(8926): E v.getLayoutParams().height = 32
10-09 12:32:06.750: I/CHEOK(8926): E v.getLayoutParams().height = 37
10-09 12:32:06.769: I/CHEOK(8926): E v.getLayoutParams().height = 42
10-09 12:32:06.785: I/CHEOK(8926): E v.getLayoutParams().height = 47
10-09 12:32:06.804: I/CHEOK(8926): E v.getLayoutParams().height = 52
10-09 12:32:06.828: I/CHEOK(8926): E v.getLayoutParams().height = 59
10-09 12:32:06.840: I/CHEOK(8926): E v.getLayoutParams().height = 62
10-09 12:32:06.863: I/CHEOK(8926): E v.getLayoutParams().height = 67
10-09 12:32:06.879: I/CHEOK(8926): E v.getLayoutParams().height = 71
10-09 12:32:06.894: I/CHEOK(8926): E v.getLayoutParams().height = 75
10-09 12:32:06.910: I/CHEOK(8926): E v.getLayoutParams().height = 79
10-09 12:32:06.929: I/CHEOK(8926): E v.getLayoutParams().height = 82
10-09 12:32:06.945: I/CHEOK(8926): E v.getLayoutParams().height = 85
10-09 12:32:06.965: I/CHEOK(8926): E v.getLayoutParams().height = 88
10-09 12:32:06.984: I/CHEOK(8926): E v.getLayoutParams().height = 89
10-09 12:32:07.000: I/CHEOK(8926): E v.getLayoutParams().height = 91
10-09 12:32:07.019: I/CHEOK(8926): E v.getLayoutParams().height = 91
10-09 12:32:07.039: I/CHEOK(8926): E v.getLayoutParams().height = -2
10-09 12:32:07.054: I/CHEOK(8926): E v.getLayoutParams().height = -2

Une nouvelle hauteur se produit toutes les ~ 20 ms. Ainsi, le FPS de l'animation est d'environ 50 images par seconde

Bien sûr, je ne peux pas simplement supprimer requestLayout, car l'interface utilisateur ne sera pas mise à jour à l'écran.

Je me demandais, y a-t-il une amélioration à faire pour réaliser une animation FPS proche de 50fps? J'avais vu un produit commercial avec un exemple d'agrandissement/effondrement fluide. Donc, je pense que c'est quelque chose de réalisable. Juste cela, je ne sais pas exactement comment.

Mon code de mise en page est le suivant:

        <LinearLayout
            Android:clickable="true"
            Android:id="@+id/chart_linear_layout"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:layout_marginTop="10dp"
            Android:layout_marginLeft="10dp"
            Android:layout_marginRight="10dp"
            Android:background="@drawable/dummy"
            Android:orientation="vertical">
            <LinearLayout
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_margin="10dp"
                Android:orientation="horizontal">
                <TextView
                    Android:layout_width="0dp"
                    Android:width="0dp"
                    Android:layout_weight="0.6"
                    Android:layout_height="wrap_content"
                    Android:gravity="left"
                    Android:textSize="20sp" 
                    Android:textColor="#ff000000"
                    Android:text="Summary chart" />
                <TextView
                    Android:id="@+id/chart_price_text_view"
                    Android:layout_width="0dp"
                    Android:width="0dp"
                    Android:layout_weight="0.4"
                    Android:layout_height="wrap_content"
                    Android:gravity="right"
                    Android:textSize="20sp" 
                    Android:textColor="#ffF76D3C"
                    Android:text="$2.99" />

            </LinearLayout>
            <TextView
                Android:visibility="gone"
                Android:id="@+id/chart_description_text_view"
                Android:layout_marginLeft="10dp"
                Android:layout_marginRight="10dp"
                Android:layout_marginBottom="10dp"
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"         
                Android:text="@string/currency_exchange_description"
                Android:textColor="#ff626262"
                Android:textSize="15sp" />                 
        </LinearLayout>

Je souhaite effectuer une animation fluide sur chart_description_text_view À partir de

Réduire (au démarrage de l'application)

enter image description here

Expansion (lorsque l'utilisateur appuie dessus)

enter image description here

L'un des "modèles de rôle" auquel je peux penser est https://play.google.com/store/apps/details? id = ch.bitspin.timely . Essayez d'appeler la boîte de dialogue ci-dessous à partir de son élément de menu Boutique . Vous réaliserez à quel point leur animation est fluide. Je ne sais pas exactement comment ils y parviennent.

enter image description here

27
Cheok Yan Cheng

Ceci est un très bon exemple sur SlideExpandibleList dans Github.

https://github.com/tjerkw/Android-SlideExpandableListView

J'espère que cela vous aidera à réaliser une animation fluide et un effondrement.

Dans cet exemple, il a enregistré l'état de l'élément de liste de développement. Donc, même si vous faites défiler la liste, il ne laissera pas fermer l'élément de liste développée.

Dans cet exemple, un événement de développement ou de réduction est donné sur Button, vous devez donc le modifier Disposition parent de l'élément de liste.

J'ai joint les captures d'écran.

J'espère que ceci vous aidera.

enter image description here

7
Amit Gupta

Vous pouvez faire Smooth Animation of View de cette façon:

public class ViewAnimationUtils {

    public static void expand(final View v) {
        v.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        final int targtetHeight = v.getMeasuredHeight();

        v.getLayoutParams().height = 0;
        v.setVisibility(View.VISIBLE);
        Animation a = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                v.getLayoutParams().height = interpolatedTime == 1
                        ? LayoutParams.WRAP_CONTENT
                        : (int)(targtetHeight * interpolatedTime);
                v.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        a.setDuration((int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }

    public static void collapse(final View v) {
        final int initialHeight = v.getMeasuredHeight();

        Animation a = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if(interpolatedTime == 1){
                    v.setVisibility(View.GONE);
                }else{
                    v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
                    v.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }
}

J'espère que cela vous aidera.

88
Hiren Patel

La façon la plus simple de faire des animations consiste à ajouter ce qui suit à votre xml pour votre mise en page linéaire:

Android:animateLayoutChanges="true"

Il fonctionne très bien et utilise des animations par défaut directement depuis Android

22
Jeremie

Il est très facile d'obtenir une animation fluide (Agrandir/Réduire) sur View

public void expandOrCollapse(final View v,String exp_or_colpse) {
    TranslateAnimation anim = null;
    if(exp_or_colpse.equals("expand"))
    {
        anim = new TranslateAnimation(0.0f, 0.0f, -v.getHeight(), 0.0f);
        v.setVisibility(View.VISIBLE);  
    }
    else{
        anim = new TranslateAnimation(0.0f, 0.0f, 0.0f, -v.getHeight());
        AnimationListener collapselistener= new AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
            v.setVisibility(View.GONE);
            }
        };

        anim.setAnimationListener(collapselistener);
    }

     // To Collapse
        //

    anim.setDuration(300);
    anim.setInterpolator(new AccelerateInterpolator(0.5f));
    v.startAnimation(anim);
}

Et utilisez cette méthode dans votre code. J'ai utilisé dans TextView et il est testé. Vous pouvez passer votre vue dans cette méthode en tant que paramètre.

        TextView tv=(TextView)findViewById(R.id.textview);
          //TO Expand 
         expandOrCollapse(tv,"expand");

        //TO Collapse
        expandOrCollapse(tv,"collapse");

ET profitez d'une réduction et d'une expansion fluides ................

16
Ashish Saini