Java 如何为布局的宽度和高度设置动画?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18742274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to animate the width and height of a Layout?
提问by P Ravikant
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
我有一个LinearLayout
通过隐藏所有其他布局和视图扩展到全屏的onClick
. 有一个Relativelayout
以上LinearLayout
I want to apply custom animation on this. The size should should increase slowly (like in 500 milli seconds).
我想对此应用自定义动画。大小应该缓慢增加(如 500 毫秒)。
But I doubt is it possible? Thanks.
但我怀疑这可能吗?谢谢。
Here is what I am doing onClick
:
这是我在做什么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()
viewId
是LinearLayout
我点击的 ID 。这个函数是从onClick()
采纳答案by Philipp Jahoda
Sure that is possible.
当然这是可能的。
Simply write your own custom-animation and modify the LayoutParams
of your animated view.
In this example, the animation animates the heightof the animated View. Of course, animating the width is also possible.
只需编写您自己的自定义动画并修改LayoutParams
您的动画视图。在这个例子中,动画动画了动画视图的高度。当然,动画宽度也是可能的。
This is how it could look like:
这是它的样子:
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;
}
}
In code, create a new Animation and apply it to the RelativeLayoutthat you want to animate:
在代码中,创建一个新的 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);
回答by Léon Pelletier
Here's a simplified, more general (any parameter of layout), Xamarin version.
这是一个简化的、更通用的(布局的任何参数)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;
}
}
Usage:
用法:
var property = "Width";
var value = 120;
var animation = new SizeAnimation(myView, property, value);
animation.Duration = 2000;
animation.Interpolator = (new LinearInterpolator());
myView.StartAnimation(animation);
"Theorically" working, not fully tested.
“理论上”工作,未完全测试。
回答by Rahul Raveendran
I worked with the answer by Philipp Jahoda
. Here is an implementation that works for both expand and collapse animations based on the start and end values we pass. Hope it helps.
我与答案一起工作Philipp Jahoda
。这是一个基于我们传递的开始和结束值适用于展开和折叠动画的实现。希望能帮助到你。
回答by ravindu1024
I was looking for this for hours and Philipp Jahoda's answer was the perfect one since it can be added to an AnimationSet as well. I made a couple of small modifications to support a more similar constructor to the default animation class (except for the View parameter) and to support the "fillEnabled" property.
我找了好几个小时,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();
}
}