web-dev-qa-db-fra.com

Comment animer la traduction d'une vue

Au premier clic sur un bouton, je veux faire glisser un View le long de l'axe x (de 200 pixels à droite disons). Et à la deuxième pression sur le bouton, je veux faire glisser le View le long de l'axe des x jusqu'à sa position d'origine.

La méthode View.setTranslationX(float) saute la vue aux emplacements horizontaux cibles avec les appels myView.setTranslationX(200); et myView.setTranslationX(0); respectivement. Quelqu'un sait comment je peux faire glisser le View vers les emplacements horizontaux cibles à la place?

Note 1: Un TranslateAnimation n'est pas bon car il ne déplace pas réellement le View mais présente seulement l'illusion de le déplacer.

Note 2: Je ne savais pas au moment de poser la question que les méthodes setTranslationX(float) et setTranslationY(float) ont été introduites à partir du niveau d'API 11. Si vous visons Honeycomb (API Niveau 11) vers le haut, alors la réponse de Gautam K suffira. Sinon, voir ma réponse pour une solution suggérée.

21
Adil Hussain

Celui-ci m'a laissé perplexe pendant quelques jours (pour le faire fonctionner avant le sandwich à la crème glacée) mais je pense que je suis enfin arrivé! (merci à Gautam K et Mike Israel pour les pistes) Ce que j'ai fait à la fin a été d'étendre mon View (un FrameLayout) pour démarrer la traduction des animations droite/gauche selon les besoins et écouter pour la fin des animations afin de déplacer mon FrameLayout droite/gauche selon le cas, comme suit:

public class SlidingFrameLayout extends FrameLayout
{
  private final int durationMilliseconds = 1000;
  private final int displacementPixels = 200;

  private boolean isInOriginalPosition = true;
  private boolean isSliding = false;

  public SlidingFrameLayout(Context context)
  {
    super(context);
  }

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

  public SlidingFrameLayout(Context context, AttributeSet attrs, int defStyle)
  {
    super(context, attrs, defStyle);
  }

  @Override
  protected void onAnimationEnd()
  {
    super.onAnimationEnd();

    if (isInOriginalPosition)
      offsetLeftAndRight(displacementPixels);
    else
      offsetLeftAndRight(-displacementPixels);

    isSliding = false;
    isInOriginalPosition = !isInOriginalPosition;
  }

  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom)
  {
    super.onLayout(changed, left, top, right, bottom);

    // need this since otherwise this View jumps back to its original position
    // ignoring its displacement
    // when (re-)doing layout, e.g. when a fragment transaction is committed
    if (changed && !isInOriginalPosition)
      offsetLeftAndRight(displacementPixels);
  }

  public void toggleSlide()
  {
    // check whether frame layout is already sliding
    if (isSliding)
      return; // ignore request to slide

    if (isInOriginalPosition)
      startAnimation(new SlideRightAnimation());
    else
      startAnimation(new SlideLeftAnimation());

    isSliding = true;
  }

  private class SlideRightAnimation extends TranslateAnimation
  {
    public SlideRightAnimation()
    {
      super(
          Animation.ABSOLUTE, 0,
          Animation.ABSOLUTE, displacementPixels,
          Animation.ABSOLUTE, 0,
          Animation.ABSOLUTE, 0);

      setDuration(durationMilliseconds);
      setFillAfter(false);
    }
  }

  private class SlideLeftAnimation extends TranslateAnimation
  {
    public SlideLeftAnimation()
    {
      super(
          Animation.ABSOLUTE, 0,
          Animation.ABSOLUTE, -displacementPixels,
          Animation.ABSOLUTE, 0,
          Animation.ABSOLUTE, 0);

      setDuration(durationMilliseconds);
      setFillAfter(false);
    }
  }
}

Et, enfin, pour faire glisser la SlidingFrameLayout droite/gauche, tout ce que vous avez à faire est d'appeler la méthode SlidingFrameLayout.toggleSlide(). Bien sûr, vous pouvez modifier ce SlidingFrameLayout à vos fins pour faire glisser un plus grand nombre de pixels, pour glisser plus longtemps, etc., mais cela devrait être suffisant pour vous aider à démarrer :)

5
Adil Hussain

Essayez de regarder ObjectAnimator et sa super classe Value Animator

vous pouvez faire quelque chose comme ça ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", 0,200); puis anim.start();

Utilisez une valeur boolean et basculez-la avec 200,0 dans l'animateur d'objet pour reculer

PS: vous pouvez utiliser la méthode setDuration pour définir la durée de l'animation.

Éditer :

Essayez de regarder la bibliothèque de support qui fournit une compatibilité descendante.

Éditer

Comme l'a souligné @AdilHussain, il existe une bibliothèque appelée nineoldandroids qui peut être utilisée dans le même but sur les androïdes plus anciens.

26
Gautam

J'ai eu un problème similaire, TranslateAnimation déplace réellement la vue si vous appelez setFillAfter maintenant ( bogue Android ). Je devais faire quelque chose de similaire alors j'ai dit, hey permet d'utiliser un écouteur d'animation et ensuite de tout déplacer au bon endroit. Malheureusement, il existe également un bug sur les écouteurs d'animation ( solution stackoverflow ). J'ai donc créé ma propre classe de mise en page selon la solution dans la solution stackoverflow et j'étais prêt à partir :)

2
MikeIsrael