Android 如何动画视图的翻译

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11188338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:15:08  来源:igfitidea点击:

How to animate a View's translation

androidandroid-animationandroid-view

提问by Adil Hussain

At the first click of a button, I want to slide a Viewalong the x-axis (by 200 pixels to the right let's say). And on the second press of the button, I want to slide the Viewback along the x-axis to its original position.

在第一次单击按钮时,我想View沿 x 轴滑动 a (比方说向右 200 像素)。在第二次按下按钮时,我想将View背面沿 x 轴滑动到其原始位置。

The View.setTranslationX(float)method jumpsthe View to the target horizontal locations with calls myView.setTranslationX(200);and myView.setTranslationX(0);respectively. Anyone know how I can slidethe Viewto the target horizontal locations instead?

View.setTranslationX(float)方法分别调用和将 View跳转到目标水平位置。任何人都知道我怎么能滑动的,而不是目标的水平位置?myView.setTranslationX(200);myView.setTranslationX(0);View

Note 1:A TranslateAnimationis no good since it doesn't actually move the Viewbut only presents the illusion of it moving.

Note 2:I didn't realise at the time of posing the question that the setTranslationX(float)and setTranslationY(float)methods were introduced as of API Level 11. If you're targeting Honeycomb (API Level 11) upwards, then Gautam K's answer will suffice. Otherwise, see my answer for a suggested solution.

注 1:ATranslateAnimation不好,因为它实际上并没有移动,View而只是呈现了它在移动的错觉。

注 2:在提出问题时我没有意识到setTranslationX(float)setTranslationY(float)方法是从 API 级别 11 开始引入的。如果您的目标是 Honeycomb(API 级别 11)向上,那么 Gautam K 的回答就足够了。否则,请参阅我的答案以获取建议的解决方案。

采纳答案by Adil Hussain

This one's had me stumped for a fair few days (getting it to work pre- Ice Cream Sandwich) but I think I've finally got there! (thanks to Gautam K and Mike Israel for the leads) What I did in the end was to extend my View(a FrameLayout) to start the translate right/left animations as required and to listen for the end of the animations in order to relocate my FrameLayoutright/left as appropriate, as follows:

这个让我难倒了好几天(让它在冰淇淋三明治之前工作)但我想我终于到了那里!(感谢 Gautam K 和 Mike Israel 的指导)我最后所做的是扩展我的View(a FrameLayout) 以根据需要开始翻译右/左动画并监听动画结束以重新定位我的FrameLayout右/left 视情况而定,如下:

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

And, lastly, to slide the SlidingFrameLayoutright/left, all you've got to do is call the SlidingFrameLayout.toggleSlide()method. Of course you can tweak this SlidingFrameLayoutfor your purposes to slide a greater number of pixels, to slide for longer etc, but this should be sufficient to get you started :)

最后,要SlidingFrameLayout向右/向左滑动,您所要做的就是调用该SlidingFrameLayout.toggleSlide()方法。当然,您可以SlidingFrameLayout根据自己的目的调整它以滑动更多像素,滑动更长时间等,但这应该足以让您开始:)

回答by Gautam

Try looking into ObjectAnimatorand its super class Value Animator

尝试查看ObjectAnimator及其超类 Value Animator

you can do something like this ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", 0,200);and then anim.start();

你可以做这样的事情 ObjectAnimator anim = ObjectAnimator.ofFloat(this, "translationX", 0,200);然后 anim.start();

Use a booleanvalue and toggle it with 200,0in the object animator to slide back

使用一个boolean值并200,0在对象动画器中切换它以向后滑动

PS: you can use setDurationmethod to set how long the animation should take to complete

PS:您可以使用setDuration方法来设置动画需要多长时间才能完成

Edit :

编辑 :

Try looking at the support librarywhich provides backward compatibility.

尝试查看提供向后兼容性的支持库

Edit

编辑

As @AdilHussain pointed out there is a library called nineoldandroidswhich can be used for the same purpose on older androids.

正如@AdilHussain 指出的那样,有一个名为Nineoldandroids的库,可用于旧机器人上的相同目的。

回答by MikeIsrael

I had a similar issue, TranslateAnimation does actually move the view if you call setFillAfter now (android bug). I had to do something similar so I said, hey lets use an animation listener and then just move everything to the correct location. Unfortunately there is a bug on animation listeners as well (stackoverflow solution). So I created my own layout class according to the solution in the stackoverflow solutionand I was good to go :)

我有一个类似的问题,如果你现在调用 setFillAfter ( android bug) ,TranslateAnimation 实际上会移动视图。我不得不做类似的事情,所以我说,嘿,让我们使用动画侦听器,然后将所有内容移动到正确的位置。不幸的是,动画侦听器也存在错误(stackoverflow 解决方案)。所以我根据stackoverflow解决方案中的解决方案创建了自己的布局类,我很高兴:)