2012-02-12 2 views
16

Хорошо, я пытаюсь создать подходящую анимацию слайдов. Представление, которое скользит вниз, должно подтолкнуть все взгляды к нему одним движением, и снова, когда он скользит, все взгляды должны следовать одним плавным движением.Android animate drop down/up view

Что я судимое: В коде:

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:

Проблема с вышеприведенным подходом заключается в том, что при первом запуске анимации создается пустое пространство для представления, а затем представление перемещается вниз. Я бы хотел, чтобы он медленно продвигал все остальные взгляды, а не делал это одним движением.

+1

Я думаю, вам нужно посмотреть на класс LayoutTransition. Он предоставляет механизмы для анимации добавления/удаления представлений в/из макета. –

ответ

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> 

Edit:

Мера высота 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

Хорошо для элементов с фуражной высотой. Но, к сожалению, этот метод не работает для элементов wrap-content :( –

+0

@bixi на самом деле это так, вам просто нужно вычислить высоту для содержимого коннекта. Это выполнимо (не удалось найти ссылку quick = /, скажите мне, если вам это нужно) – Warpzit

+0

Отличный пример: вы также можете повторно использовать View.VISIBLE и View.GONE, чтобы указать тип (результат анимации) – Bostone

5

Спасибо Warpzit! Это был очень полезный ответ. В моем случае я только пытался анимировать представления с высотой, которая была wrap_content. Я попробовал двухстрочное предложение тригг, но в моем случае это не сработало. (Я не проводил много времени провожу почему.) Я закончил с использованием слегка модифицированной формы Warpzit-х ExpandCollapseAnimation с его статическим методом, чтобы определить высоту зрения

В чуть более подробно:

  1. Я включил свой статический метод setHeightForWrapContent() в класс ExpandCollapseAnimation.
  2. Я вызываю setHeightForWrapContent() в конструкторе ExpandCollapseAnimation, чтобы правильно определить высоту представления.Для этого мне нужно передать действие с помощью конструктора.
  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! –