7

I have a LinearLayout which is expanded to full screen by hiding all other layouts and views on onClick. There is a Relativelayout above LinearLayout

I want to apply custom animation on this. The size should should increase slowly (like in 500 milli seconds).

But I doubt is it possible? Thanks.

Here is what I am doing 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 is the id of the LinearLayout I am clicking. This function is called from onClick()

4

4 回答 4

18

当然这是可能的。

只需编写您自己的自定义动画并修改LayoutParams您的动画视图。在此示例中,动画会为动画 View的高度设置动画。当然,也可以为宽度设置动画

这就是它的样子:

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

在代码中,创建一个新的 Animation 并将其应用到要设置动画的 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);
于 2013-09-11T13:24:12.850 回答
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();
}
}
于 2016-08-31T02:57:56.567 回答
1

我与答案一起工作Philipp Jahoda。这是一个基于我们传递的开始和结束值适用于展开和折叠动画的实现。希望能帮助到你。

https://gist.github.com/rahulrvp/dcccd1b78cd09b31a024

于 2015-11-07T11:43:53.083 回答
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);

“理论上”有效,未经过全面测试。

于 2015-10-31T05:21:37.243 回答