2013-08-16 58 views
18

所以我用动画的动画视图:请查看动画在最终动画中的位置

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    android:interpolator="@android:anim/accelerate_interpolator" > 

    <translate 
     android:duration="1000" 
     android:fromYDelta="0%" 
     android:toYDelta="-75%" /> 

</set> 

它在视觉上我想要的,但我也想冻结这个动画的结果。就像我需要以某种方式得到结果布局参数(或其他东西?)后动画,并将其设置为布局。假设布局Y坐标从0变为100,但我并不知道什么是起始坐标和结果坐标。我需要得到结果坐标并将其设置为布局因为如果不这样做,动画布局返回到其初始位置,但我需要使它保持在新位置而不是返回。另外我需要2.3.x兼容解决方案。
更新1
我也试过NineOldAndroids:

ObjectAnimator.ofFloat(rootWrapper, "translationY", -rootWrapper.getHeight()*75/100).start(); 

这个动画的观点和看法停留在动画的位置 - 这就是正是我想达到的。
但是,所有控件都保持虚拟位置。即使你的布局只能看到它底部的25%,如果我点击那个空白的屏幕区域,然后按钮的onClick触发(其中有b4动画),剩余75%的屏幕看起来是空的。如果设置了xml-animtaions,也会发生同样的情况

animation.setFillAfter(true); 

如何解决该问题?所有的控件必须随着视图移动。
更新2
代码:

public void showAbout(){ 

     final Animation animShow = AnimationUtils.loadAnimation(this, R.anim.about_in_from_bottom); 
     animShow.setFillAfter(true); 

     //ObjectAnimator.ofFloat(rootWrapper, "translationY", -rootWrapper.getHeight()*75/100).start(); 

     animShow.setAnimationListener(new AnimationListener() { 

      @Override 
      public void onAnimationStart(Animation animation) { 
      } 

      @Override 
      public void onAnimationRepeat(Animation animation) {} 

      @Override 
      public void onAnimationEnd(Animation animation) { 
       LinearLayout.LayoutParams rootlp = (LinearLayout.LayoutParams) rootWrapper.getLayoutParams(); 
       Log.i(this,"rootlp: h: "+rootlp.topMargin+ "/w: "+rootlp.bottomMargin); 
       rootlp.topMargin = -rootlp.height*75/100; 
       rootWrapper.setLayoutParams(rootlp); 
      } 
     }); 

     rootWrapper.startAnimation(animShow); 
    } 

我得到了这个问题 - rootlp.height返回0的Cuz它像MATCH_PARENT或喜欢。它不会返回REAL像素,而是一些代表某些常量的值!所以看起来我有两个玩.getViewTreeObserver().addOnGlobalLayoutListener
好吧,我通过getViewTreeObserver()获得了rootWrapper的真正高度。现在使用公式rootlp.topMargin = -rootlp.height*75/100;我收到了更多问题。
1)动画View之后另外移动(由于设置LP)。
2)动画视图包含的控件(必须随父视图一起向上移动的按钮)虚拟地停留在它们的位置(它们不可见但可点击)!在视觉上,这些控件随着动画视图向上移动,我无法触及它(它离开屏幕)。但是,如果我点击区域,他们之前动画相应onClick()触发!多么有趣!
UPDATE 3
最后我达到了我的目标!问题在于移动View的子容器。我在想,如果我移动一些视图,那么它的所有子视图也在移动。但事实并非如此,我必须在动画完成后手动移动子视图以修复幽灵按钮。

+0

你为什么试图在动画之后得到LayoutParams?你想让视图停留在动画位置吗? –

+0

是的,正是我想要的2do。 – Stan

+0

那么看到我的anser并使用setFillAfter(); –

回答

41

请考虑setFillAfter(boolean);将其设置为true将使视图停留在动画位置。

Animation anim = new TranslateAnimation(0, 0, 0, 100); 

// or like this 
Animation anim = AnimationUtils.loadAnimation(this, R.anim.animation_name); 

anim.setFillAfter(true); 
anim.setDuration(1000); 

这可以通过使用ViewPropertyAnimator,可从API 14及以后完成更容易:

int animationpos = 500; 
View.animate().y(animationpos).setDuration(1000); // this will also keep the view at the animated position 

或者考虑的AnimationListener动画后得到的LayoutParams正是:

anim.setAnimationListener(new AnimationListener() { 

      @Override 
      public void onAnimationStart(Animation animation) {} 

      @Override 
      public void onAnimationRepeat(Animation animation) {} 

      @Override 
      public void onAnimationEnd(Animation animation) { 
        // get layoutparams here and set it in this example your views 
        // parent is a relative layout, please change that to your desires 

        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) View.getLayoutParams(); 
        lp.topMargin = yournewtopmargin // use topmargin for the y-property, left margin for the x-property of your view 
        View.setLayoutParams(lp); 
       } 
      }); 

    View.startAnimation(anim); 

UPDATE:

如何知道视图移动了多少像素,取决于动画的 百分比值?

您的.xml动画中的百分比值与动画视图的尺寸(如宽度和高度)相关。因此,您只需要使用您的视图的宽度和高度属性(取决于天气您使用x或y动画以像素为单位获得实际动画距离)。

例如:

您的视图的宽度为400像素。您的动画将x属性从0%动画到75%,这意味着您的视图将300像素(400 * 0.75)移动到右侧。所以onAnimationEnd(),将LayoutParams.leftMargin设置为300,你的视图将具有所需的位置。

+0

thanx! anim.setFillAfter(真);做的伎俩,但所有的控制保持虚拟(不可见)在他们的立场。请检查我的更新1。 – Stan

+0

看到animationlistener,尤其是我的答案中的animationEnd方法:)你可以得到layoutParams并设置它充分 –

+0

是的,但是如何知道导致yournewtopmargin的动画?这是我的问题的一部分,因为我已经试图在onAnimationEnd中设置LP,然后再问问题,但卡住了要设置的值。 – Stan

0

您可以根据需要使用NineOldAndroid代理库来使用ObjectAnimator。它支持较低的API级别,并使用本机库来实现较新的API级别。

只需简单地导入为LibraryProject,它会很好。

+1

就像我在我的问题中提到的,我已经试过了。这导致了一些关于幽灵控制的问题也在我的Q. – Stan

2

我发现简单地将fillEnabled和fillAfter设置为TRUE并不能解决像click/touch监听器这样的问题。设置填充启用和填充后才是真正的只是确保视图的像素在正确的最终位置DRAWN。但是,假设动画视图具有与之关联的onclick监听器。在新的可见位置单击视图将不会执行任何操作,但单击视图最初位置的屏幕将触发onClick。

以下是如何解决这样一个例子:

假设我们有一个观点与onClickListener设置它。假设视图范围是0,0,0,0(左,上,右,下)。 现在假设我们希望将视图向右移动200.下面的代码将演示如何以将要绘制的像素和底层视图对象移动到正确位置的方式执行此操作,从而调整onClick从正确的位置被调用。

private Animation generateMoveRightAnimation() { 
    final Animation animation = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 200, 
      Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0); 
    animation.setDuration(300); 
    animation.setFillAfter(true); 
    animation.setFillEnabled(true); 

    animation.setAnimationListener(new Animation.AnimationListener() { 
     @Override 
     public void onAnimationStart(Animation animation) { 

     } 

     @Override 
     public void onAnimationEnd(Animation animation) { 
      RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) view.getLayoutParams(); 
      // change the coordinates of the view object itself so that on click listener reacts to new position 
      view.layout(view.getLeft()+200, view.getTop(), view.getRight()+200, view.getBottom()); 
      repeatLevelSwitch.clearAnimation(); 
     } 

     @Override 
     public void onAnimationRepeat(Animation animation) { 

     } 
    }); 

    return animation; 
} 
+0

中描述,这个答案值得更多的关注.. – BiGGZ

+0

@BiGGZ你的意思是我需要添加更多的细节? – TomTaila

+0

不,因为它是一个很好的答案 – BiGGZ