更改 android 视图的位置似乎会更改动画枢轴
Changing the position of an android view appears to change the animation pivot
我正在使用 Xamarin (C#),但 Java 解决方案很好。
我有一个自定义 parent 视图和一个 child 视图。 parent 具有固定的大小和位置,child 应该 扩展 到用户点击 parent 的视图中。 expand 动画是一个简单的淡入和缩放动画,应该围绕 child.
的中心旋转
我目前看到的结果是 child 总是在 parent 的 upper-left 角开始播放动画,并且似乎转换为用户点击的点适当缩放和褪色。这让我认为动画枢轴以某种方式受到干扰。
如何移动 child 元素并确保应用到它的动画仍然围绕局部中心点旋转,以及究竟是什么导致了我目前看到的这种行为?
编辑:我发现根本原因是动画缩放了 child 的 x 和 y 坐标及其宽度和高度,因此当scale 为 0 时,child 出现在 parent 元素的原点,当 scale 为 1 时,它出现在正确的位置。我现在的新问题是:我可以使用什么方法将 child 绝对定位在 parent 中而不受缩放的影响?
谢谢。
Parent 查看 Class
public class Parent: RelativeLayout
{
private RelativeLayout _child;
private Animation _animation;
private LayoutParams _layoutParams;
public Parent(Context context, IAttributeSet attrs)
: base(context, attrs)
{
_layoutParams = new RelativeLayout.LayoutParams(64, 64);
_child = new RelativeLayout(context);
_child.LayoutParameters = _layoutParams;
_child.SetBackgroundColor(Color.Red);
_child.Visibility = ViewStates.Invisible;
this.AddView(_child);
_animation = AnimationUtils.LoadAnimation(context, Resource.Animation.Expand);
_animation.AnimationEnd += OnAnimationEnd;
this.Touch += OnTouch;
}
private void OnTouch(object sender, View.TouchEventArgs e)
{
// position the top left of the child view such that
// the center point lies over the touch point
var x = e.Event.GetX() - (_child.Width / 2);
var y = e.Event.GetY() - (_child.Height / 2);
_child.SetX(x);
_child.SetY(y);
_child.StartAnimation(_animation);
_child.Visibility = ViewStates.Visible;
}
}
展开动画资源
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"
android:shareInterpolator="true"
android:duration="500" >
<scale
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" >
</scale>
<alpha
android:fromAlpha="0"
android:toAlpha="1" />
</set>
我现在可以使用此动画,尽管新方法与其说是解决方案,不如说是一种变通方法。
通过以编程方式创建动画并将枢轴绝对设置在父级内,我能够确保子位置和枢轴每次都完美对齐:
private void OnTouch(object sender, View.TouchEventArgs e)
{
// position the top left of the child view such that
// the center point lies over the touch point
var x = e.Event.GetX() - (_child.Width / 2);
var y = e.Event.GetY() - (_child.Height / 2);
_child.SetX(x);
_child.SetY(y);
// define the animation with the pivot absolutely positioned over the center of the child
var animation = new AnimationSet(true);
animation.Interpolator = new DecelerateInterpolator();
animation.Duration = 500;
animation.AddAnimation(new AlphaAnimation(0.4F, 0F));
animation.AddAnimation(new ScaleAnimation(0F, 4F, 0F, 4F,
Dimension.Absolute, x,
Dimension.Absolute, y));
_child.StartAnimation(animation);
_child.Visibility = ViewStates.Visible;
}
如果有一种解决方案允许使用动画资源并且不需要绝对值,那么会更加简洁。
我正在使用 Xamarin (C#),但 Java 解决方案很好。
我有一个自定义 parent 视图和一个 child 视图。 parent 具有固定的大小和位置,child 应该 扩展 到用户点击 parent 的视图中。 expand 动画是一个简单的淡入和缩放动画,应该围绕 child.
的中心旋转我目前看到的结果是 child 总是在 parent 的 upper-left 角开始播放动画,并且似乎转换为用户点击的点适当缩放和褪色。这让我认为动画枢轴以某种方式受到干扰。
如何移动 child 元素并确保应用到它的动画仍然围绕局部中心点旋转,以及究竟是什么导致了我目前看到的这种行为?
编辑:我发现根本原因是动画缩放了 child 的 x 和 y 坐标及其宽度和高度,因此当scale 为 0 时,child 出现在 parent 元素的原点,当 scale 为 1 时,它出现在正确的位置。我现在的新问题是:我可以使用什么方法将 child 绝对定位在 parent 中而不受缩放的影响?
谢谢。
Parent 查看 Class
public class Parent: RelativeLayout
{
private RelativeLayout _child;
private Animation _animation;
private LayoutParams _layoutParams;
public Parent(Context context, IAttributeSet attrs)
: base(context, attrs)
{
_layoutParams = new RelativeLayout.LayoutParams(64, 64);
_child = new RelativeLayout(context);
_child.LayoutParameters = _layoutParams;
_child.SetBackgroundColor(Color.Red);
_child.Visibility = ViewStates.Invisible;
this.AddView(_child);
_animation = AnimationUtils.LoadAnimation(context, Resource.Animation.Expand);
_animation.AnimationEnd += OnAnimationEnd;
this.Touch += OnTouch;
}
private void OnTouch(object sender, View.TouchEventArgs e)
{
// position the top left of the child view such that
// the center point lies over the touch point
var x = e.Event.GetX() - (_child.Width / 2);
var y = e.Event.GetY() - (_child.Height / 2);
_child.SetX(x);
_child.SetY(y);
_child.StartAnimation(_animation);
_child.Visibility = ViewStates.Visible;
}
}
展开动画资源
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"
android:shareInterpolator="true"
android:duration="500" >
<scale
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" >
</scale>
<alpha
android:fromAlpha="0"
android:toAlpha="1" />
</set>
我现在可以使用此动画,尽管新方法与其说是解决方案,不如说是一种变通方法。
通过以编程方式创建动画并将枢轴绝对设置在父级内,我能够确保子位置和枢轴每次都完美对齐:
private void OnTouch(object sender, View.TouchEventArgs e)
{
// position the top left of the child view such that
// the center point lies over the touch point
var x = e.Event.GetX() - (_child.Width / 2);
var y = e.Event.GetY() - (_child.Height / 2);
_child.SetX(x);
_child.SetY(y);
// define the animation with the pivot absolutely positioned over the center of the child
var animation = new AnimationSet(true);
animation.Interpolator = new DecelerateInterpolator();
animation.Duration = 500;
animation.AddAnimation(new AlphaAnimation(0.4F, 0F));
animation.AddAnimation(new ScaleAnimation(0F, 4F, 0F, 4F,
Dimension.Absolute, x,
Dimension.Absolute, y));
_child.StartAnimation(animation);
_child.Visibility = ViewStates.Visible;
}
如果有一种解决方案允许使用动画资源并且不需要绝对值,那么会更加简洁。