Yet Another [à compléter]

MfA Tricks #7 - Eye-candy Using Layout Animations

Since Android 3.0 (API level 11), a lot of effort went into improving the amount of eye-candy in the system while making it easier for third party developers to do the same for their applications.

One of such improvements is to provide an easy way to automatically add animation to existing ViewGroup elements (i.e. every layout objects) without having to code them up.

Indeed, when using the android:animateLayoutChanges attribute with a ViewGroup, a set of default animations are registered on its children views during layout changes.

By default, visibility and size modifications are taken into account. The first produce a fadein/fadeout effect and the second produces a slidein/slideout animation.

These two default effects can be used together with a LinearLayout to make a nice transition between two states of the same widget:

In the video, my widget has two different presentation modes, one for user selection and the other for drag-and-drop interaction. The latter mode is triggered by an user action (starting the drag).

Here is the relevant part of my layout XML for the widget skeleton:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="16dp"
    android:layout_marginTop="16dp"
    android:layout_marginRight="16dp"
    android:animateLayoutChanges="true"
    android:id="@+id/animatedLayout">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="7dp"
        android:id="@+id/mode1">

		<!-- Widget mode 1 layout -->

    </LinearLayout>
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="1px"
        android:layout_gravity="center"
        android:id="@+id/mode2">

        <!-- Widget mode 2 layout -->

    </LinearLayout>
</LinearLayout>

The outer LinearLayout is the one that contains the android:animateLayoutChanges attribute. Both widget modes are also LinearLayout objects.

Since the first mode is the one shown by default, its layout height is set to wrap_content whereas the second mode layout is artificially hidden by setting its height to 1 pixel.

To go from mode 1 to mode 2, I use the following code in the drag started event handler:

var parms = mode2.LayoutParameters as LinearLayout.LayoutParams;
parms = new LinearLayout.LayoutParams (parms) {
	Height = ViewGroup.LayoutParams.WrapContent,
	Gravity = GravityFlags.Center
};
mode2.LayoutParameters = parms;
mode1.Visibility = ViewStates.Gone;

And to go the other way, we simply restore the XML state we had beforehand with a similar code:

mode1.Visibility = ViewStates.Visible;
var parms = mode2.LayoutParameters as LinearLayout.LayoutParams;
parms = new LinearLayout.LayoutParams (parms) {
	Height = 1,
	Gravity = GravityFlags.Center
};
mode2.LayoutParameters = parms;

Comments