Question

I have this layout for testing some Animations.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/frame1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#00ff00"
        android:orientation="vertical">
        <TextView
            android:id="@+id/text1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="1"/>
        <TextView
            android:id="@+id/text2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="2"/>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/frame2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#0000ff">

        <ListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/edit_style"/>

    </LinearLayout>
</LinearLayout>

What I want to achive is that the ListView list in the LinearLayout frame2 should grow to the top of the screen, while the LinearLayout frame1 shrinks.

This can be done very easily with the ObjectAnimator and an AnimatorSet like this:

ObjectAnimator animframe1 = ObjectAnimator.ofInt(frame1, "bottom", 0);
ObjectAnimator animframe2 = ObjectAnimator.ofInt(frame2, "top", 0);
ObjectAnimator listview = ObjectAnimator.ofInt(list, "bottom", frame2.getBottom());

AnimatorSet set = new AnimatorSet();
set.setDuration(1000L);
set.playTogether(animframe1, animframe2, listview);
set.start();

What I do is manipulating the top and the bottom properties of the Views to have the grow/shrink effect.

It works like I want, but with one flaw: While the ListView is growing, the additional items (which are there) aren't visible. The room should be there, but the additional items will only show up if I click the ListView after the animation.

How can I say the ListView that the additional items should be reloaded while the animation runs?

I tried to call list.invalidate() in an AnimationUpdateListener but without success. If I call list.requestLayout() there will be no Animation.

Was it helpful?

Solution

What I have missed is to set the height of the ListView, after the top property was modified. Without this the ListView will hold the same old height, which is the reason that no additional items will be shown.

I switched to a ValueAnimator, because there is no need for an additional setter for the height in a CustomListView class.

Code is like this:

public void animateListHeight() {
    PropertyValuesHolder topList = PropertyValuesHolder.ofInt("top", mListView.getTop(), 5);

    ValueAnimator animList = ValueAnimator.ofPropertyValuesHolder(topList);
    animList.setDuration(300L);

    AnimatorUpdateListener listUpdater = new AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int top = ((Integer)animation.getAnimatedValue("top")).intValue();
            mListView.setTop(top);
            ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) mListView.getLayoutParams();
            params.height = mListView.getBottom() - top;
            mListView.setLayoutParams(params);
        }
    };

    animList.addUpdateListener(listUpdater);
    animList.start();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top