我有一个LinearLayout
,它通过隐藏onClick
上的所有其他布局和视图而扩展到全屏。 Relativelayout
LinearLayout
我想对此应用自定义动画。尺寸应该缓慢增加(如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()
答案 0 :(得分:16)
当然可以。
只需编写自己的自定义动画并修改动画视图的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);
答案 1 :(得分:2)
我正在寻找这个好几个小时,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();
}
}
答案 2 :(得分: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);
“理论上”工作,未经充分测试。
答案 3 :(得分:1)
我通过Philipp Jahoda
处理了答案。这是一个适用于基于我们传递的起始值和结束值的展开和折叠动画的实现。希望它有所帮助。