2012-02-12 35 views
16

好吧我正在嘗試做一個適當的向下滑動動畫。下滑的觀點應該將所有的觀點都以一種平滑的運動推向下方,再次當它向上滑動時,所有的觀點都應該以一種平滑的運動進行。Android動畫下拉/向上視圖正確

我已經tryed: 在代碼:

LinearLayout lin = (LinearLayout)findViewById(R.id.user_list_container); 
       setLayoutAnimSlidedownfromtop(lin, this); 
       lin.addView(getLayoutInflater().inflate(R.layout.user_panel,null),0); 

和:

public static void setLayoutAnimSlidedownfromtop(ViewGroup panel, Context ctx) { 

     AnimationSet set = new AnimationSet(true); 

     Animation animation = new AlphaAnimation(0.0f, 1.0f); 
     animation.setDuration(100); 
     set.addAnimation(animation); 

     animation = new TranslateAnimation(
      Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, 
      Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f 
    ); 
     animation.setDuration(500); 
     set.addAnimation(animation); 

     LayoutAnimationController controller = 
      new LayoutAnimationController(set, 0.25f); 
     panel.setLayoutAnimation(controller); 

} 

我user_panel.xml:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="40dp" 
    android:orientation="vertical" > 
    <ImageView 
     android:layout_alignParentLeft="true" 
     android:layout_height="wrap_content" 
     android:layout_width="wrap_content" 
     android:src="@drawable/icon" /> 
</LinearLayout> 

頂部主要的xml:

<LinearLayout 
     android:id="@+id/user_list_container" 
     android:layout_alignParentTop="true" 
     android:orientation="vertical" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content"/> 
    <LinearLayout 
     android:id="@+id/container" 
     android:layout_below="@+id/user_list_container" 
     android:orientation="vertical" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content"> 

上述方法的問題是,當我首先啓動動畫時,視圖的空白空間被創建,然後視圖滑落。我希望它能夠緩慢推動所有其他的觀點,而不是在一個困難的議案中進行。

+1

我認爲你需要看'LayoutTransition'類。它提供了動畫添加/刪除/從佈局視圖的機制。 – 2012-02-12 13:07:17

回答

56

所以我最終自己做了一些幫助:https://stackoverflow.com/a/9112691/969325。 如果它是Android 3.0(http://developer.android.com/guide/topics/graphics/animation.html)我可以使用屬性動畫,但它不是我必須自己做的。

這裏是我結束了:

import android.view.View; 
import android.view.animation.Animation; 
import android.view.animation.Transformation; 

/** 
* Class for handling collapse and expand animations. 
* @author Esben Gaarsmand 
* 
*/ 
public class ExpandCollapseAnimation extends Animation { 
    private View mAnimatedView; 
    private int mEndHeight; 
    private int mType; 

    /** 
    * Initializes expand collapse animation, has two types, collapse (1) and expand (0). 
    * @param view The view to animate 
    * @param duration 
    * @param type The type of animation: 0 will expand from gone and 0 size to visible and layout size defined in xml. 
    * 1 will collapse view and set to gone 
    */ 
    public ExpandCollapseAnimation(View view, int duration, int type) { 
     setDuration(duration); 
     mAnimatedView = view; 
     mEndHeight = mAnimatedView.getLayoutParams().height; 
     mType = type; 
     if(mType == 0) { 
      mAnimatedView.getLayoutParams().height = 0; 
      mAnimatedView.setVisibility(View.VISIBLE); 
     } 
    } 

    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
     super.applyTransformation(interpolatedTime, t); 
     if (interpolatedTime < 1.0f) { 
      if(mType == 0) { 
       mAnimatedView.getLayoutParams().height = (int) (mEndHeight * interpolatedTime); 
      } else { 
       mAnimatedView.getLayoutParams().height = mEndHeight - (int) (mEndHeight * interpolatedTime); 
      } 
      mAnimatedView.requestLayout(); 
     } else { 
      if(mType == 0) { 
       mAnimatedView.getLayoutParams().height = mEndHeight; 
       mAnimatedView.requestLayout(); 
      } else { 
       mAnimatedView.getLayoutParams().height = 0; 
       mAnimatedView.setVisibility(View.GONE); 
       mAnimatedView.requestLayout(); 
       mAnimatedView.getLayoutParams().height = mEndHeight; 
      } 
     } 
    } 
} 

例ussage:

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

public class AnimationTestActivity extends Activity { 
    private boolean mActive = false; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     final Button animatedButton = (Button) findViewById(R.id.animatedButton); 

     Button button = (Button) findViewById(R.id.button); 
     button.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       ExpandCollapseAnimation animation = null; 
       if(mActive) { 
        animation = new ExpandCollapseAnimation(animatedButton, 1000, 1); 
        mActive = false; 
       } else { 
        animation = new ExpandCollapseAnimation(animatedButton, 1000, 0); 
        mActive = true; 
       } 
       animatedButton.startAnimation(animation); 
      } 
     }); 
    } 
} 

XML:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 
    <Button 
     android:id="@+id/animatedButton" 
     android:visibility="gone" 
     android:layout_width="fill_parent" 
     android:layout_height="50dp" 
     android:text="@string/hello"/> 
    <TextView 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="@string/hello" /> 
    <Button 
     android:id="@+id/button" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="@string/hello"/> 
</LinearLayout> 

編輯

措施WRAP_CONTENT高度:

因此,爲了得到這個爲WRAP_CONTENT工作,我測量的視線的高度之前,我開始播放動畫,然後用這個測量高度的實際高度。貝婁是用於測量視圖的高度代碼並將此作爲新的高度(我假設的視圖使用屏幕寬度,根據自己的需要改變):

/** 
* This methode can be used to calculate the height and set it for views with wrap_content as height. 
* This should be done before ExpandCollapseAnimation is created. 
* @param activity 
* @param view 
*/ 
public static void setHeightForWrapContent(Activity activity, View view) { 
    DisplayMetrics metrics = new DisplayMetrics(); 
    activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); 

    int screenWidth = metrics.widthPixels; 

    int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 
    int widthMeasureSpec = MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.EXACTLY); 

    view.measure(widthMeasureSpec, heightMeasureSpec); 
    int height = view.getMeasuredHeight(); 
    view.getLayoutParams().height = height; 
} 
+0

確定forcer-height元素。但不幸的是,這種方法不適用於包裝內容元素:( – 2012-06-01 16:04:14

+0

@bixi實際上它的確如此,你只需要計算包裝內容的高度。它是可行的(做到了,但找不到引用quick = /,告訴我你是否需要它) – Warpzit 2012-08-28 06:31:26

+0

很好的例子!你也可以重用View.VISIBLE和View.GONE來指示類型(動畫結果) – Bostone 2012-09-17 14:56:39

5

謝謝Warpzit!這是一個非常有用的答案。在我的情況下,我只是試圖使用wrap_content的高度對視圖進行動畫處理。我嘗試了triggers兩行建議,但在我的情況下它不起作用。 (我並沒有花太多時間追求爲什麼。)最後我用Warpzit的ExpandCollapseAnimation與他的靜態方法的稍加修改,以確定視圖

的高度稍微詳細:

  1. 我在ExpandCollapseAnimation類中包含了他的靜態方法setHeightForWrapContent()
  2. 我在ExpandCollapseAnimation構造函數中調用setHeightForWrapContent()來正確確定視圖的高度。要做到這一點,我必須通過構造函數來傳遞活動。
  3. applyTransformation()方法中,當視圖最終降至零高度時,我將視圖的高度返回到wrap_content。如果您不這樣做,並稍後更改視圖的內容,那麼當您展開視圖時,視圖將展開到先前確定的高度。

的代碼是在這裏:

public class ExpandCollapseAnimation extends Animation { 
    private View mAnimatedView; 
    private int mEndHeight; 
    private int mType; 

    public ExpandCollapseAnimation(View view, int duration, int type, Activity activity) { 
     setDuration(duration); 
     mAnimatedView = view; 

     setHeightForWrapContent(activity, view); 

     mEndHeight = mAnimatedView.getLayoutParams().height; 

     mType = type; 
     if(mType == 0) { 
      mAnimatedView.getLayoutParams().height = 0; 
      mAnimatedView.setVisibility(View.VISIBLE); 
     } 
    } 

    @Override 
    protected void applyTransformation(float interpolatedTime, Transformation t) { 
     super.applyTransformation(interpolatedTime, t); 
     if (interpolatedTime < 1.0f) { 
      if(mType == 0) { 
       mAnimatedView.getLayoutParams().height = (int) (mEndHeight * interpolatedTime); 
      } else { 
       mAnimatedView.getLayoutParams().height = mEndHeight - (int) (mEndHeight * interpolatedTime); 
      } 
      mAnimatedView.requestLayout(); 
     } else { 
      if(mType == 0) { 
       mAnimatedView.getLayoutParams().height = mEndHeight; 
       mAnimatedView.requestLayout(); 
      } else { 
       mAnimatedView.getLayoutParams().height = 0; 
       mAnimatedView.setVisibility(View.GONE); 
       mAnimatedView.requestLayout(); 
       mAnimatedView.getLayoutParams().height = LayoutParams.WRAP_CONTENT;  // Return to wrap 
      } 
     } 
    } 

    public static void setHeightForWrapContent(Activity activity, View view) { 
     DisplayMetrics metrics = new DisplayMetrics(); 
     activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); 

     int screenWidth = metrics.widthPixels; 

     int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 
     int widthMeasureSpec = MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.EXACTLY); 

     view.measure(widthMeasureSpec, heightMeasureSpec); 
     int height = view.getMeasuredHeight(); 
     view.getLayoutParams().height = height; 
    } 
} 

再次感謝您,Warpzit!

+0

這個作品,awsome! – 2017-02-10 13:04:47