Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
326 views
in Technique[技术] by (71.8m points)

android - Keep animated View at final Animation Position

So I'm animating a view using animation:

<?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>

It does visually what I want but I also I want to freeze result of this animation. Like I need somehow to get resulting layout parameters (or something else?) after animation and set it to layout. Assume layout Y-coord is changing from 0 to 100 but I don't really know what was starting coords and what are resulting coords. I need to get resulting coords and set it to the layout cuz if wouldn't do so layout returns back to its initial position after animation but I need to make it stay in new position instead of returning back. Also I need 2.3.x compatible solution.
UPDATE 1
I also tried NineOldAndroids:

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

this animates the view and view stays at animated position - thats exactly what I want to achieve.
However all controls stays at their positions virtually. Even thou layout is only visible by 25% of its bottom part and 75% of rest screen looks empty if I tap that empty screen area then button's (which was there b4 animation) onClick triggered. The same happens with xml-animtaions if set

animation.setFillAfter(true); 

How to fix that issue? All controls has to move with the view.
UPDATE 2
The code:

    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);
    }

I got the problem - rootlp.height returns 0 cuz its like MATCH_PARENT or like. It wont return the REAL pixels but some value representing some constant! So it looks like I have 2 play with .getViewTreeObserver().addOnGlobalLayoutListener.
Ok, I got the real height of rootWrapper via getViewTreeObserver(). And now using the formula rootlp.topMargin = -rootlp.height*75/100; I'm getting even more issues.
1) After animation View moves up additionally (due to setting LP).
2) Controls that animated View contains (buttons which has to move up with the parent View) stays at their positions virtually (they are invisible but clickable)! Visually those controls are moved up with the animated View and I can't reach it (it goes off the screen). But if I tap area where they was before animation corresponding onClick() triggers! What a fun!
UPDATE 3
Finally I had achieved my goal! The problem was with moving View's child containers. I was thinking that if I move some View then all of its child views are also moving. But thats not the case and I was had to move child views manually after animation completes to fix ghost buttons.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Please consider setFillAfter(boolean); setting it to true will make the view stay at the animated position.

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);

This can be done even easier using the ViewPropertyAnimator, available from API 14 and onwards:

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

Or consider an AnimationListener to get the LayoutParams exactly after the animation:

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);

UPDATE:

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

The percentage value in your .xml animation is relative to the animated View's dimensions (such as width and height). Therefore, you just need to use your View's width and height properties (depending on weather u use x or y animation to get the actual animation distance in pixels).

For example:

Your View has a width of 400 pixels. Your animation animates the x-property from 0% to 75%, meaning that your view will move 300 pixels (400 * 0.75) to the right side. So onAnimationEnd(), set the LayoutParams.leftMargin to 300 and your View will have the desired position.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...