Android动画下拉/上视图正确

Android动画下拉/上视图正确,android,animation,view,Android,Animation,View,好的,我正在做一个适当的向下滑动动画。向下滑动的视图应以一个平滑的运动将其下方的所有视图向下推,再次,当其向上滑动时,所有视图应以一个平滑的运动跟随 我所尝试的: 代码: LinearLayout lin = (LinearLayout)findViewById(R.id.user_list_container); setLayoutAnimSlidedownfromtop(lin, this); lin.addView(getLa

好的,我正在做一个适当的向下滑动动画。向下滑动的视图应以一个平滑的运动将其下方的所有视图向下推,再次,当其向上滑动时,所有视图应以一个平滑的运动跟随

我所尝试的: 代码:

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

My 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">


上述方法的问题是,当我首先启动动画时,会创建视图的空白空间,然后视图向下滑动。我希望它能慢慢地向下推所有其他视图,而不是一个硬动作。

因此,我在以下人员的帮助下完成了这项工作:。 如果是安卓3.0(),我可以使用属性动画,但不是这样,我必须自己做

以下是我的结论:

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


谢谢你!这是一个非常有用的答案。在我的例子中,我只是尝试用包裹内容的高度设置视图的动画。我尝试了triggs的两行建议,但在我的情况下不起作用。(我没有花太多时间去寻找原因。)我最终使用了Warpzit的
ExpandCollapseAnimation
的一种稍加修改的形式和他的静态方法来确定视图的高度

稍微详细一点:

  • 我将他的静态方法
    setHeightForWrapContent()
    包含在
    ExpandCollapseAnimation
    类中
  • 我在
    ExpandCollapseAnimation
    构造函数中调用
    setHeightForWrapContent()
    ,以正确确定视图的高度。为此,我必须将活动与构造函数一起传递
  • applyTransformation()
    方法中,当视图最终降低到零高度时,我将视图的高度返回到wrap\u内容。如果不执行此操作,并在以后更改视图的内容,则展开视图时,视图将展开到先前确定的高度
  • 代码在这里:

    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;
        }
    }
    
    public类ExpandCollapseAnimation扩展动画{
    私人视图mAnimatedView;
    私家车高度;
    私有int-mType;
    公共ExpandCollapseAnimation(视图、整型持续时间、整型类型、活动){
    设置持续时间(持续时间);
    mAnimatedView=视图;
    设置WrapContent(活动、视图)的高度;
    mEndHeight=mAnimatedView.getLayoutParams().height;
    mType=类型;
    如果(mType==0){
    mAnimatedView.getLayoutParams().height=0;
    mAnimatedView.setVisibility(View.VISIBLE);
    }
    }
    @凌驾
    受保护的无效应用转换(浮点插值时间,转换t){
    超级应用转换(插值时间,t);
    如果(插值时间<1.0f){
    如果(mType==0){
    mAnimatedView.getLayoutParams().height=(int)(mEndHeight*interpolatedTime);
    }否则{
    mAnimatedView.getLayoutParams().height=mEndHeight-(int)(mEndHeight*interpolatedTime);
    }
    mAnimatedView.requestLayout();
    }否则{
    如果(mType==0){
    mAnimatedView.getLayoutParams().height=mEndHeight;
    mAnimatedView.requestLayout();
    }否则{
    mAnimatedView.getLayoutParams().height=0;
    mAnimatedView.setVisibility(View.GONE);
    mAnimatedView.requestLayout();
    mAnimatedView.getLayoutParams().height=LayoutParams.WRAP\u CONTENT;//返回到WRAP
    }
    }
    }
    公共静态void setHeightForWrapContent(活动、视图){
    DisplayMetrics=新的DisplayMetrics();
    activity.getWindowManager().getDefaultDisplay().getMetrics(度量);
    int screenWidth=metrics.widthPixels;
    int heightMeasureSpec=MeasureSpec.MakeMasureSpec(0,MeasureSpec.Unspected);
    int-widthmasurespec=MeasureSpec.makeMeasureSpec(屏幕宽度,精确测量);
    视图测量(宽度测量、高度测量);
    int height=view.getMeasuredHeight();
    view.getLayoutParams().height=高度;
    }
    }
    

    再次感谢你,沃普齐特

    我认为您需要查看
    LayoutTransition
    类。它提供了在布局中添加/删除视图的动画机制。确定forcer高度元素。但不幸的是,此方法不适用于包裹内容元素:(@bixi实际上是这样,您只需计算包裹内容的高度。这是可行的(做了但找不到引用quick=/,如果需要请告诉我)很好的示例!您还可以重用View.VISIBLE和View.Goe以指示类型(动画结果)将
    mEndHeight=mAnimatedView.getLayoutParams().height;
    替换为
    mEndHeight=type==0?mAnimatedView.getLayoutParams().height:mAnimatedView.getMeasuredHeight();
    并且它将使用
    包装内容
    ,而不需要额外的方法
    setHeightForWrapContent(活动,视图)
    Oh,还需要
    if(mEndHeight<0)mEndHeight=mAnimatedView.getMeasuredHeight();
    (如果视图开始最小化,则没有它
    mEndHeight
    将为-2)
    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 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>
    
    /**
     * 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;
    }
    
    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;
        }
    }