且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Android 动画下拉/上视图正确

更新时间:2022-12-26 20:07:09

所以我最终在 this answer 的帮助下自己完成了.如果是 Android 3.0,我可以使用属性动画,但这不是我必须自己做的.

So I ended up doing it myself with some help from this answer. If it had been Android 3.0, I could have used property animation, but it's not so I had to do that myself.

这是我最后的结果:

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;
            }
        }
    }
}

示例用法:

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 能够使用它,我在开始动画之前测量了视图的高度,然后将测量的高度用作实际高度.下面是测量视图高度并将其设置为新高度的代码(我假设视图使用屏幕宽度,根据您自己的需要更改):

So in order to get this to work for wrap_content, I measured the height of the view before I start the animation and then use this measured height as the actual height. Below is the code for measuring the height of the view and set this as the new height (I assume the view uses screen width, change according to your own needs):

/**
 * This method 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;
}