在最终动画位置保持动画视图

Sta*_*tan 21 animation android

所以我用动画制作视图动画:

<?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>
Run Code Online (Sandbox Code Playgroud)

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

ObjectAnimator.ofFloat(rootWrapper, "translationY", -rootWrapper.getHeight()*75/100).start();
Run Code Online (Sandbox Code Playgroud)

这使得视图和视图保持动画位置的动画 - 这正是我想要实现的.
然而,所有控件都是虚拟的.如果我点击那个空屏幕区域然后按钮(那里有b4动画)onClick触发,即使你的布局只有25%的底部可见,75%的休息屏幕看起来是空的.如果设置了xml-animtaions,也会发生同样的情况

animation.setFillAfter(true); 
Run Code Online (Sandbox Code Playgroud)

如何解决这个问题?所有控件都必须随视图移动.
更新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);
    }
Run Code Online (Sandbox Code Playgroud)

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

Phi*_*oda 51

请考虑setFillAfter(boolean); 将其设置为true将使视图保持在动画位置.

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);
Run Code Online (Sandbox Code Playgroud)

使用可从API 14及以后版本获得的ViewPropertyAnimator可以更轻松地完成此操作:

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

或者考虑使用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);
Run Code Online (Sandbox Code Playgroud)

更新:

如何知道视图移动了多少像素,具体取决于动画的百分比值?

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

例如:

您的视图宽度为400像素.您的动画将x属性设置为0%到75%,这意味着您的视图将向右侧移动300像素(400*0.75).因此onAnimationEnd(),将LayoutParams.leftMargin设置为300,您的View将具有所需的位置.