【问题标题】:Android View with a translate animation - positioning is not working as expected带有翻译动画的 Android 视图 - 定位未按预期工作
【发布时间】:2017-08-03 16:31:56
【问题描述】:

我有一个具有OnClickListener 的视图。单击时,视图会平移到页面上的某个位置。这没问题,视图在它应该去的地方。再次单击视图时,我想将其放置在其他位置,但事实并非如此。经过一些故障排除后,我发现我的 View 的 getTop() 方法返回相同的值 - 即使在翻译动画将视图移动到屏幕的不同部分之后也是如此。对于第二个动画,它没有使用当前位置(如我所料),而是使用初始位置。

我正在做的几件事:我使用ObjectAnimation 类而不是TranslationAnimation 类,因为我想保持OnClickListener 正常工作。使用TranslationAnimation 类,我发现视图已正确移动,但OnClickListener 仅在视图开始的区域中工作。使用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 轴向上平移,偏移量决定了 View 需要从其当前位置移动多远。

现在,这是第二次点击时发生的情况。这里的目标是将视图与父级的基础对齐。

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 的原始位置。

【问题讨论】:

    标签: android animation


    【解决方案1】:

    你可以像这样得到屏幕最底部的坐标:

    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 毫秒的持续时间非常快,在屏幕上翻译内容通常看起来并不酷,因此您可能希望将其设置得更高一点,但这只是个人喜好问题。

    【讨论】:

    • 这不能按预期工作。例如,我将位置从 A 移动到 B,然后尝试将视图(在单击按钮时,在第一个动画完成后)从 B 移动到 C。我调用 child.animate().translationY(0).setInterpolator(new AccelerateDecelerateInterpolator()).setDuration(250);。这会将视图移回其原始位置。这是没有意义的,因为translationY() 应该将视图转换为指定的浮动位置。 translationY(0) 不应该将视图移动到屏幕顶部吗?相反,它被送回它开始的地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 2018-10-31
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 2023-03-31
    相关资源
    最近更新 更多