如何为一个布局添加宽度和高度的动画效果?

7

我有一个LinearLayout,在onClick上隐藏所有其他布局和视图,并展开到全屏。在LinearLayout上方有一个Relativelayout

我想对此应用自定义动画。大小应该缓慢增加(如在500毫秒内)。

但我怀疑这是否可能?谢谢。

这是我在onClick中所做的:

private void expandView (int viewId) {
    RelativeLayout relativeLayout = (RelativeLayout) ((LinearLayout) view.findViewById(viewId)).getParent();
    ViewGroup.MarginLayoutParams rlMargin = (ViewGroup.MarginLayoutParams) relativeLayout.getLayoutParams();
    rlMargin.setMargins(0, 0, 0, 0);
    relativeLayout.setLayoutParams(rlMargin);
    LinearLayout linearLayout = (LinearLayout) relativeLayout.getParent();
    hideAllLinearLayoutExcept(linearLayout.getId());
    hideAllTilesExcept(viewId);
}

viewId是我正在点击的LinearLayout的id。这个函数是从onClick()中调用的。


你想要动画RelativeLayout的宽度和高度吗? - Philipp Jahoda
是的,它会自动增加大小。 - Pramod Ravikant
好的,看下面我的回答。 - Philipp Jahoda
4个回答

18

当然可以。

只需编写自己的自定义动画,并修改动画视图的 LayoutParams。 在此示例中,动画会使动画视图的高度 发生变化。当然,也可以动画化宽度

以下是示例:

public class ResizeAnimation extends Animation {

    private int startHeight;
    private int deltaHeight; // distance between start and end height
    private View view;

    /**
     * constructor, do not forget to use the setParams(int, int) method before
     * starting the animation
     * @param v
     */
    public ResizeAnimation (View v) {
        this.view = v;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {

        view.getLayoutParams().height = (int) (startHeight + deltaHeight * interpolatedTime);
        view.requestLayout();
    }

    /**
     * set the starting and ending height for the resize animation
     * starting height is usually the views current height, the end height is the height
     * we want to reach after the animation is completed
     * @param start height in pixels
     * @param end height in pixels
     */
    public void setParams(int start, int end) {

        this.startHeight = start;
        deltaHeight = end - startHeight;
    }

    /**
     * set the duration for the hideshowanimation
     */
    @Override
    public void setDuration(long durationMillis) {
        super.setDuration(durationMillis);
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}   

在代码中,创建一个新的动画并将其应用于要动画化的RelativeLayout:
RelativeLayout relativeLayout = (RelativeLayout) ((LinearLayout) view.findViewById(viewId)).getParent();

// getting the layoutparams might differ in your application, it depends on the parent layout
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) relativeLayout.getLayoutParams();

ResizeAnimation a = new ResizeAnimation(relativeLayout);
a.setDuration(500);

// set the starting height (the current height) and the new height that the view should have after the animation
a.setParams(lp.height, newHeight);

relativeLayout.startAnimation(a);

刚在我的一个应用程序的底部工作表中使用了这个,唯一有效的答案!非常感谢你! - Nick Mowen
这太完美了。谢谢!顺便说一下,我添加了一个答案,稍微修改了你的代码,使其更通用。 - ravindu1024

3

我找了好几个小时,Philipp Jahoda的答案是最完美的,因为它可以添加到AnimationSet中。我对它进行了一些小修改,以支持更类似于默认动画类(除了View参数)的构造函数,并支持"fillEnabled"属性。

public class ResizeAnimation extends Animation
{

private int startWidth;
private int deltaWidth; // distance between start and end height
private int startHeight;
private int deltaHeight;

private int originalWidth;
private int originalHeight;
private View view;

private boolean fillEnabled = false;


public ResizeAnimation(View v, int startW, int endW, int startH, int endH)
{
    view = v;
    startWidth = startW;
    deltaWidth = endW - startW;

    startHeight = startH;
    deltaHeight = endH - startH;

    originalHeight = v.getHeight();
    originalWidth = v.getWidth();
}

@Override
public void setFillEnabled(boolean enabled)
{
    fillEnabled = enabled;
    super.setFillEnabled(enabled);
}


@Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
    if(interpolatedTime == 1.0 && !fillEnabled)
    {
        view.getLayoutParams().height = originalHeight;
        view.getLayoutParams().width = originalWidth;
    }
    else
    {
        if(deltaHeight != 0)
            view.getLayoutParams().height = (int) (startHeight + deltaHeight * interpolatedTime);
        if(deltaWidth != 0)
            view.getLayoutParams().width = (int) (startWidth + deltaWidth * interpolatedTime);
    }

    view.requestLayout();
}
}

1
这是一个简化的、更通用(适用于任何布局参数)的 Xamarin 版本。
public class SizeAnimation : Animation 
{
    private int _newValue;
    private int _initialValue;
    private string _property;
    private object _target;
    private View _view;

    public SizeAnimation (View view, string property, int newValue)
    {
        _view = view;
        _property = property;
        _newValue = newValue;
        _target = view.LayoutParameters;

        // View measure is generally an enum of wrap_content / fill_parent
        // we need to make the measure explicit
        if (property == "Width" || property == "Height")
        {
            view.Measure ((int)MeasureSpecMode.Unspecified, (int)MeasureSpecMode.Unspecified);
            var unmeasuredValue = (int)view.GetType().GetProperty(property).GetValue(view);
            _initialValue = unmeasuredValue < 1
                ? (int) view.GetType().GetProperty("Measured" + _property).GetValue(view)
                : unmeasuredValue;

            view.LayoutParameters.GetType().GetProperty(property).SetValue(view.LayoutParameters,_initialValue);
        } else
        {
            _initialValue = (int) _target.GetType ().GetProperty (property).GetValue(_target);
        }
    }

    protected override void ApplyTransformation(float interpolatedTime, Transformation t) 
    {
        _target.GetType().GetProperty(_property).SetValue(_target, (int)(_initialValue + (_newValue - _initialValue) * interpolatedTime));
        _view.RequestLayout();  
    }

    public override bool WillChangeBounds() 
    {
        return true;
    }
}

使用方法:

var property = "Width";
var value = 120;
var animation = new SizeAnimation(myView, property, value);
animation.Duration = 2000;
animation.Interpolator = (new LinearInterpolator());
myView.StartAnimation(animation);

"理论上"可以工作,但尚未完全测试。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接