带有翻译动画的Android视图 - 定位无法正常工作

时间:2016-01-27 00:31:28

标签: android animation

我有一个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年的原始位置。

1 个答案:

答案 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毫秒的持续时间非常快,并且通常不会在屏幕上显示很酷的翻译内容,因此您可能希望将其设置得更高,但这仅仅是品味问题。