6

In Android, is it possible to apply an animation on layout_gravity ? for example suppose I want to change the layout_gravity of a View(e.g. Button) from right to left

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Button"
        android:id="@+id/button"
        android:layout_gravity="right|top" />
</FrameLayout>

In the above layout file I want to change layout gravity from right|top to left|top at run-time with animation, is it possible at all? Thanks

frogatto
  • 28,539
  • 11
  • 83
  • 129

2 Answers2

7

You can use a LayoutTransition on the parent ViewGroup to make it animate changes to child views, such as layout changes. In the example below, I animate a floating action button from bottom right of the screen to top right, whilst also rotating it (so the '+' icon becomes an 'x' icon).

Set animateLayoutChanges to true on your containing layout:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/pnlFabContainer"
    android:animateLayoutChanges="true"
    android:clipChildren="false">

    <ExpandableListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white"
        android:id="@+id/lstWhatever"
        android:divider="@color/DividerDarkGrey"
        android:dividerHeight="1dp"
        android:choiceMode="singleChoice"
        android:groupIndicator="@null"
        android:padding="20dp"/>

    <com.melnykov.fab.FloatingActionButton
        android:id="@+id/fabMultiSelect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="24dp"
        android:src="@drawable/button_plus"
        android:scaleType="center"
        fab:fab_type="normal"
        fab:fab_colorNormal="@color/FloatingActionButton"
        fab:fab_colorPressed="@color/FloatingActionButtonPressed"
        fab:fab_colorRipple="@color/FloatingActionButtonRipple" />

</FrameLayout>

Enable the 'changing' transition on your container:

FrameLayout pnlFabContainer = (FrameLayout)view.findViewById(R.id.pnlFabContainer);
LayoutTransition transition = pnlFabContainer.getLayoutTransition();
transition.enableTransitionType(LayoutTransition.CHANGING);

animateFabButton(fab);

Then change your layout gravity programmatically - I'm also doing a rotate animation at the same time:

protected void animateFabButton(FloatingActionButton fab) {
    if (fab.isSelected()) {
        FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)fab.getLayoutParams();
        layoutParams.gravity = Gravity.TOP | Gravity.END;
        layoutParams.topMargin = -(fab.getMeasuredHeight() / 2);
        fab.setLayoutParams(layoutParams);

        Animation rotate = new RotateAnimation(0, 45, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotate.setFillBefore(true);
        rotate.setFillAfter(true);
        rotate.setFillEnabled(true);
        rotate.setDuration(750);
        rotate.setRepeatCount(0);
        rotate.setInterpolator(new LinearInterpolator());
        fab.startAnimation(rotate);
    }
    else {
        FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)fab.getLayoutParams();
        layoutParams.gravity = Gravity.BOTTOM | Gravity.END;
        layoutParams.topMargin = layoutParams.bottomMargin;
        fab.setLayoutParams(layoutParams);

        Animation rotate = new RotateAnimation(45, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotate.setFillBefore(true);
        rotate.setFillAfter(true);
        rotate.setFillEnabled(true);
        rotate.setDuration(750);
        rotate.setRepeatCount(0);
        rotate.setInterpolator(new LinearInterpolator());
        fab.startAnimation(rotate);
    }
}
Breeno
  • 3,007
  • 2
  • 31
  • 30
1

Its not possible with the layout_gravity attribute. You can achieve the effect with the help of translate animation which runs forever.

Animation animation = new TranslateAnimation(0, 500,0, 0);
animation.setDuration(1000);
animation.setFillAfter(true);
myImage.startAnimation(animation);

This code will only change the position to +500 on x axis

Hardik4560
  • 3,202
  • 1
  • 20
  • 31