我有一个OnClickListener
的视图。单击时,视图会转换为页面上的某个位置。这没有问题,视图应该在哪里。再次单击视图时,我想将其放在其他位置,但事实并非如此。在拍摄一些麻烦之后,我发现我的View的getTop()方法返回相同的值 - 即使在翻译动画将视图移动到屏幕的其他部分之后也是如此。对于第二个动画,它没有使用当前位置(正如我所料),而是使用初始位置。
我正在做的事情很少:我使用ObjectAnimation
类而不是TranslationAnimation
类,因为我想保持OnClickListener
的功能。使用TranslationAnimation
类,我发现视图已正确移动,但OnClickListener
仅适用于View开始的区域。使用ObjectAnimation
课程,我能够轻松地使翻译工作并且OnClickListener
功能正常 - 它会在视图当前在屏幕上的位置被触发。
这是我到目前为止所拥有的:
final LinearLayout child = layouts.get(i); //ArrayList containing some dynamic layouts
final int offset = target - child.getTop();
ObjectAnimator anim = ObjectAnimator.ofFloat(child,"translationY",offset);
anim.setDuration(250);
anim.start();
这是第一次点击视图时发生的情况。它沿Y轴向上平移,偏移量决定了视图从当前位置移动的距离。
现在,这是第二次点击时发生的事情。这里的目标是将视图与父母的基础对齐。
target = parent.getBottom();
offset = target - child.getTop();
anim = ObjectAnimator.ofFloat(child, "translationY",offset);
anim.setDuration(250);
anim.start();
prev = child;
这就是事情崩溃的地方 - child.getTop()
返回视图的原始位置的Y坐标。不是现在的位置。因此,在动画之后,视图位于父级底部的下方。我读了一个不同的问题,说明我应该使用child.getY()
来代替translationY
位置加上top
位置,但这并没有带来更好的结果。我似乎无法使其正常工作。我只想将视图从当前位置移动到屏幕底部,但这似乎很难实现。任何帮助,将不胜感激。
修改
我添加了动画监听器:
ObjectAnimator anim = ObjectAnimator.ofFloat(child,"translationY",offset);
anim.setDuration(250);
anim.addListener(new ObjectAnimator.AnimatorListener(){
@Override
public void onAnimationStart(Animator animation) {
System.out.println("start: " + child.getTop() + " " + child.getY());
}
@Override
public void onAnimationEnd(Animator animation) {
System.out.println("end: " + child.getTop() + " " + child.getY() + " " + child.getTranslationY());
child.setTop((int)child.getY());
System.out.println(child.getTop());
}
@Override
public void onAnimationCancel(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
});
anim.start();
这里我设置监听器以尝试更改视图顶部的位置。行为再次无法按预期工作。当我这样做时,视图实际上是在屏幕上方发送的。 System.out的输出如下所示:
start: 2008 2008.0
end: 2008 478.0 -1530.0
478
所以在动画完成后调用child.getTop()
并设置一个新位置会返回一个正整数,但视图实际上并不完全在屏幕上。它位于屏幕上方,部分可见。视图本身的高度约为700px。我仍然很困惑,为什么这是一件很难完成的事情。
编辑2
我还尝试在onAnimationEnd
方法中设置layoutparams:
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)child.getLayoutParams();
params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
params.topMargin = (int)child.getY();
child.setLayoutParams(params);
结果:child.getTop()
仍然返回2008年的原始位置。
答案 0 :(得分:0)
您可以像这样获得屏幕坐标的最底部:
float bottomOfScreen = getResources().getDisplayMetrics().heightPixels;
但您可能希望它减去LinearLayout的高度,否则您的LinearLayout将被底部切断:
float bottomOfScreen = getResources().getDisplayMetrics().heightPixels
- child.getHeight();
// if you want a little more space to the bottom
// try something like - child.getHeight()*2;
然后使用ViewPropertyAnimator为LL制作动画,如下所示:
child.animate()
.translationY(bottomOfScreen)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setDuration(250);
插值器只是为了使动画更逼真。
如果child.getHeight()返回0,则系统尚未完成线性布局设置,在这种情况下,您可能需要执行以下操作:
child.post(new Runnable() {
@Override
public void run() {
float bottomOfScreen = getResources().getDisplayMetrics().heightPixels
- child.getHeight()*2;
child.animate()
.translationY(bottomOfScreen)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setDuration(250);
}
});
请记住,250毫秒的持续时间非常快,并且通常不会在屏幕上显示很酷的翻译内容,因此您可能希望将其设置得更高,但这仅仅是品味问题。