2013-08-16 100 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