android - 将动画 View 保持在最终动画位置

标签 android animation

所以我正在使用动画制作 View :

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_interpolator" >

    <translate
        android:duration="1000"
        android:fromYDelta="0%"
        android:toYDelta="-75%" />

</set>

它在视觉上做了我想要的,但我也想卡住这个动画的结果。就像我需要在动画之后以某种方式获取结果布局参数(或其他东西?)并将其设置为布局。假设布局 Y 坐标从 0 变为 100,但我真的不知道什么是起始坐标以及什么是结果坐标。我需要获取结果坐标并将其设置为布局,因为如果不这样做,布局会在动画后返回到其初始位置,但我需要让它保持在新位置而不是返回。我还需要 2.3.x 兼容的解决方案。
更新 1
我也试过 NineOldAndroids:

ObjectAnimator.ofFloat(rootWrapper, "translationY", -rootWrapper.getHeight()*75/100).start();

这会为 View 设置动画,并且 View 保持在动画位置 - 这正是我想要实现的。
但是所有控件实际上都保持在它们的位置。即使您的布局仅在其底部的 25% 处可见,并且如果我点击那个空白屏幕区域然后按钮的(那里是 b4 动画)onClick 触发,则其余屏幕的 75% 看起来是空的。如果设置了 xml-animtaions 也会发生同样的情况

animation.setFillAfter(true); 

如何解决这个问题?所有控件都必须随 View 移动。
更新 2
代码:

    public void showAbout(){

        final Animation animShow = AnimationUtils.loadAnimation(this, R.anim.about_in_from_bottom);
        animShow.setFillAfter(true); 

        //ObjectAnimator.ofFloat(rootWrapper, "translationY", -rootWrapper.getHeight()*75/100).start();

        animShow.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationRepeat(Animation animation) {}

            @Override
            public void onAnimationEnd(Animation animation) {
                LinearLayout.LayoutParams rootlp = (LinearLayout.LayoutParams) rootWrapper.getLayoutParams();
                Log.i(this,"rootlp: h: "+rootlp.topMargin+ " / w: "+rootlp.bottomMargin);
                rootlp.topMargin = -rootlp.height*75/100;
                rootWrapper.setLayoutParams(rootlp);
            }
        });

        rootWrapper.startAnimation(animShow);
    }

我遇到了问题 - rootlp.height 返回 0 因为它类似于 MATCH_PARENT 或类似。它不会返回真正的像素,而是一些代表某个常数的值!所以看起来我有 2 次玩 .getViewTreeObserver().addOnGlobalLayoutListener.
好的,我通过 getViewTreeObserver() 得到了 rootWrapper 的真实高度。现在使用公式 rootlp.topMargin = -rootlp.height*75/100; 我遇到了更多问题。
1)动画后 View 额外向上移动(由于设置 LP )。
2)动画 View 包含的控件(必须与父 View 一起向上移动的按钮)几乎保持在它们的位置(它们不可见但可点击)!在视觉上,这些控件随着动画 View 向上移动,我无法到达它(它离开了屏幕)。但是,如果我在相应的 onClick() 触发动画之前点击它们所在的区域!多么有趣!
更新 3
我终于达到了我的目标!问题在于移动 View 的子容器。我在想,如果我移动一些 View ,那么它的所有 subview 也会移动。但事实并非如此,我不得不在动画完成后手动移动 subview 以修复幽灵按钮。

最佳答案

请考虑 setFillAfter(boolean); 将其设置为 true 将使 View 停留在动画位置。

Animation anim = new TranslateAnimation(0, 0, 0, 100);

// or like this
Animation anim = AnimationUtils.loadAnimation(this, R.anim.animation_name);

anim.setFillAfter(true); 
anim.setDuration(1000);

使用 API 14 及更高版本提供的 ViewPropertyAnimator 可以更轻松地完成此操作:

int animationpos = 500;
View.animate().y(animationpos).setDuration(1000); // this will also keep the view at the animated position

或者考虑一个 AnimationListener 在动画之后获取 LayoutParams:

anim.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {}

            @Override
            public void onAnimationRepeat(Animation animation) {}

            @Override
            public void onAnimationEnd(Animation animation) {
                  // get layoutparams here and set it in this example your views 
                  // parent is a relative layout, please change that to your desires

                  RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) View.getLayoutParams();
                  lp.topMargin = yournewtopmargin // use topmargin for the y-property, left margin for the x-property of your view
                  View.setLayoutParams(lp);
                }
            });

    View.startAnimation(anim);

更新:

How to know how many pixels the view moved, depending on the percentage values of the animation?

.xml 动画中的百分比值是相对于动画 View 的尺寸(例如宽度和高度)。因此,您只需要使用您的 View 的宽度和高度属性(根据天气你使用 x 或 y 动画来获取以像素为单位的实际动画距离)。

例如:

您的 View 的宽度为 400 像素。您的动画将 x 属性从 0% 设置为 75%,这意味着您的 View 将向右侧移动 300 像素 (400 * 0.75)。所以 onAnimationEnd(),将 LayoutParams.leftMargin 设置为 300,你的 View 就会有想要的位置。

关于android - 将动画 View 保持在最终动画位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18269338/

相关文章:

android - Android 中的蓝牙配对。连接丢失时调用的事件

ios - (Cocos2D) Sprite 没有完美地位于其他 sprite 之上?

Android 使用 ImageView 淡入淡出

Python:在动画中在plot_surface()上绘制的网格线

objective-c - 使用 SceneKit 从 DAE/COLLADA 中提取动画顶点

Android + 以编程方式通过蓝牙配对设备

android - Android Studio 中的 "Failed to get the compiler information for file ..."

android - 在主屏幕小部件中实现 ListView

java - 无法使用 OpenTok 在耳机模式下切换音频

java - 从 JComponent 的右下角动画缩小会导致卡顿