Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animating weightSum property using ObjectAnimator

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

like image 280
Entreco Avatar asked Dec 01 '11 12:12

Entreco


1 Answers

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

like image 195
Entreco Avatar answered Oct 21 '22 21:10

Entreco