DarkLeafyGreen
DarkLeafyGreen

Reputation: 70466

Android translate animation instantly requires full height while animating

So imagine you have a parent relative layout with height set to wrap_content. Inside this layout is another layout which is hidden by default. This is how I reveal it:

view.startAnimation(AnimationUtils.loadAnimation(context, R.anim.translate_in));
view.setVisibility(View.VISIBLE);  

Here is the corresponding anim file. It basically moves the view from the bottom to the top.

 <translate
    android:duration="250"
    android:fromXDelta="0"
    android:fromYDelta="100%p"
    android:toXDelta="0"
    android:toYDelta="0"
    android:fillAfter="true"/>

I expect the parent view to change its height according to the animation of the child view. However when the animation starts the parent view instantly shifts up while the child view is still animating. It feels like the setVisibility is called before the animation has finished.

So to solve this I would scale the height of the child from 0 to 100%, however I do not want a scale but a translate effect.

Any ideas how to approach this problem?

The layout is simple:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:backgroundColor="@color/grey">

    <TextView/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:backgroundColor="@color/white"
        android:visibility="GONE">

        <TextView/>

     </RelativeLayout>

</RelativeLayout>

Upvotes: 0

Views: 2323

Answers (1)

Jiang Qi
Jiang Qi

Reputation: 4448

    final RelativeLayout parent = null;//parent relative layout
    final View child = null;//parent relative layout child

    final int initParentHeight=parent.getHeight();

    parent.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            parent.getViewTreeObserver().removeOnPreDrawListener(this);

            int finalParentHeight = parent.getHeight();//get parent final height
            final ViewGroup.LayoutParams layoutParams = parent.getLayoutParams();
            ValueAnimator animator = ValueAnimator.ofInt(initParentHeight, finalParentHeight);
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    layoutParams.height = (int) animation.getAnimatedValue();
                    parent.requestLayout();//animate height change
                }
            });
            animator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;//reset parent layoutparams height to wrap_content
                    parent.requestLayout();
                }
            });
            animator.setDuration(250);
            animator.start();
            return true;
        }
    });
    child.setVisibility(View.VISIBLE);

Upvotes: 3

Related Questions