Animating weightSum property using ObjectAnimator
Asked Answered
W

1

7

Intro:

I have a LinearLayout, which contains two sub LinearLayouts, like so:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dual_pane"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal"
    android:weightSum="1.0">

    <!-- Screen 1 -->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:background="#ff0000"
        android:layout_weight="1">
    </LinearLayout>

    <!-- Screen 2 -->
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:background="#ff6600"
        android:layout_weight="1">
    </LinearLayout>
</LinearLayout>

Initially, I want "Screen 1" to take all screen width available. Therefore, my R.id.dual_pane has it's weightSum attribute to 1.0. This works fine! if weightSum=1.0, Screen 1 occupies the whole screen!

After loading some resources, I change my R.id.dual_pane weighSum to 2.0, which results in both Screen 1 and Screen 2 taking 50% off the width of the screen. This also works perfect. When weightSum=2.0, both screens take 50% of the width.

Problem:

I would like to animate the weightSum property, so my Screen2 will slide in. I am targeting HoneyComb, so minSDK version is 11, and I figured, using the new ObjectAnimator framework, I could easily animate this property, to get a nice smooth effect. I verified that LinearLayout indeed has getWeightSum() and setWeightSum() methods (which is required to use the ObjectAnimator, I think).

Own effort:

Here's my code to showing and hiding Screen2 using the ObjectAnimator :

private void showScreen2()
{
    //Not-animated will work...
    //mDualPane.setWeightSum(2.0f);

    // Now try to animate the weightSum
    float ws = mDualPane.getWeightSum();
    ObjectAnimator anim = ObjectAnimator.ofFloat(mDualPane, "weightSum", ws, 2.0f);
    anim.setDuration(5000);
    anim.start();
}

private void hideScreen2()
{
    //Not-animated will work...
    //mDualPane.setWeightSum(1.0f);

    // Now try to animate the weightSum
    float ws = mDualPane.getWeightSum();
    ObjectAnimator anim = ObjectAnimator.ofFloat(mDualPane, "weightSum", ws, 1.0f);
    anim.setDuration(5000);
    anim.start();
}

Here, my mDualPane is my root LinearLayout...

Question:

When I call these functions, nothing happens. The screen stays exactly like it was before. Do I need to call requestLayout() on my mDualPane somewhere? Am I missing some knowledge of the ObjectAnimator? Or is it impossible to animate the weightSum property?

ALSO:

1) I don't want to mess with hard-coded widths, and animate those. For now I want 50-50 for both screens, but I might change it later. Anyway, i need to be able to set a specific ratio between the two widths.

2) I have looked at LayoutTransition combined with toggling visibility, but to no avail

Wassyngton answered 1/12, 2011 at 12:55 Comment(0)
W
11

I was right in the sense that I need to update the layout myself:

float ws = mDualPane.getWeightSum();
ObjectAnimator anim = ObjectAnimator.ofFloat(mDualPane, "weightSum", ws, 2.0f);
anim.setDuration(5000);
anim.addUpdateListener(this);
anim.start();

Now, I added an UpdateListener to the ObjectAnimator, which is implemented by my Activity and updates the layout:

@Override
public void onAnimationUpdate(ValueAnimator animation) {
    mDualPane.requestLayout();
}

It seems strange to me, that ObjectAnimator doesn't call this itself, but anyway, this is how to get it working.

The solution is especially nice, in my opinion, since you can very nicely animate layouts sliding in, independent of screensize...

Wassyngton answered 8/12, 2011 at 11:23 Comment(5)
hi,Entreco if two linear layouts having unequal weights then, can we make this possible to move right side layout to left side and filling whole screen? please helpDelainedelainey
Unfortunately, this only works for sliding views from left to right, due to the nature of LinearLayout. For doing this the other way around, I suggest you look at #4932962Wassyngton
my two view are also in LinearLayout itself but with unequal weightsDelainedelainey
I implemented this solution but got the problem that though requestLayout is called, my right side view is not really growing. Is that what you mean by "only works from left to right"? Because I want my right side to grow, which means the border slides towards the left...Milewski
calling requestLayout() in onAnimationUpdate() is a bad idea, since it's easy to exceed 16 ms limit. For any more or less complex layout you are guaranteed to have stutters. That's why ObjectAnimator doesn't do this by default.Matthus

© 2022 - 2024 — McMap. All rights reserved.