21

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

View.setTranslationX(float)方法分别调用和将视图跳转到目标水平位置。任何人都知道我可以如何滑动到目标水平位置?myView.setTranslationX(200);myView.setTranslationX(0);View

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

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

4

3 回答 3

26

尝试查看ObjectAnimator及其超类 Value Animator

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

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

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

编辑 :

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

编辑

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

于 2012-06-25T11:21:12.417 回答
5

这个让我难倒了好几天(让它在冰淇淋三明治之前工作)但我想我终于到了那里!(感谢 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);
    }
  }
}

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

于 2012-07-03T11:08:14.107 回答
2

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

于 2012-06-25T11:28:01.723 回答