Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sliding layer activity animation android

I want to implement sliding-layer animation for activity transition as described in material design guidelines.

Material Transition

However, all I could do by now is a simple combination of slide_in and stay animation which doesn't give me a stacked layer kind of effect. How can I achieve it?

My current implementation :

On Activity Start:

activity.overridePendingTransition(R.anim.slide_in_right, R.anim.stay);

On Activity Close:

activity.overridePendingTransition(R.anim.stay, R.anim.slide_out_right);

slide_in_right.xml:

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_interpolator">
    <translate
        android:fromXDelta="100%p"
        android:toXDelta="0"
        android:duration="@android:integer/config_shortAnimTime" />
</set>

slide_out_right.xml:

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_interpolator">
    <translate
        android:fromXDelta="0"
        android:toXDelta="100%p"
        android:duration="@android:integer/config_shortAnimTime" />
</set>

stay.xml:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_shortAnimTime"
    android:fromYDelta="0%p"
    android:toYDelta="0%p" />
like image 919
Gaurav Arora Avatar asked Dec 15 '14 11:12

Gaurav Arora


2 Answers

I have finally found a solution for this question. It works flawless.

The important components used in this answer:

  • BackActivity = background activity
  • FrontActivity = activity that slides in front
  • BackgroundView = the base ViewGroup in your FrontActivity

The solution is to animate the layout of the FrontActivity out before closing the FrontActivity. This is only possible if you use a toolbar integrated in your layout as your action bar!

I will copy my code here. My animation is an activity that slides in front from the bottom, and dissapears again sliding out to the bottom in front of the previous activity. You can easily get this effect in any direction by just altering the animations.


1) Slide FrontActivity in over BackActivity
Just call overridePendingTransition when starting FrontActivity from BackActivity.

Intent intent = new Intent(activity, FrontActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.slide_in_bottom, 0);

slide_in_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="100%p"
    android:toYDelta="0%p"
    android:duration="@android:integer/config_mediumAnimTime"
    android:interpolator="@android:anim/decelerate_interpolator">
</translate>

2) When going back from FrontActivity to BackActivity, animate the layout from FrontActivity out before you close FrontActivity!

I did this by calling the following method in my onOptionsSelected() and my onBackPressed() in FrontActivity

private void animateOut() {
    Animation slideAnim = AnimationUtils.loadAnimation(this,R.anim.slide_out_bottom);
    slideAnim.setFillAfter(true);;
    slideAnim.setAnimationListener(new AnimationListener() {
        public void onAnimationStart(Animation paramAnimation) { }
        public void onAnimationRepeat(Animation paramAnimation) { }
        public void onAnimationEnd(Animation paramAnimation) { 
            finish();
            // if you call NavUtils.navigateUpFromSameTask(activity); instead, 
            // the screen will flicker once after the animation. Since FrontActivity is 
            // in front of BackActivity, calling finish() should give the same result.
            overridePendingTransition(0, 0);
        }
    });
    BackgroundView.startAnimation(slideAnim);
}

slide_out_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="0%p"
    android:toYDelta="100%p"
    android:duration="@android:integer/config_mediumAnimTime"
    android:interpolator="@android:anim/accelerate_interpolator">
</translate>

3) Now we have to make sure BackActivity is visible behind FrontActivity when it animates out.
We need to work with transparent themes for this.

styles.xml

<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- your theme -->
    </style>

    <style name="Theme.Transparent" parent="AppTheme">
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowBackground">@android:color/transparent</item>
    </style>

</resources>

4) Apply the transparent theme to FrontActivity in your manifest:

AndroidManifest.xml

<activity
      android:name=".FrontActivity"
      android:theme="@style/Theme.Transparent"
      android:parentActivityName=".BackActivity" />

5) Because your activity is now transparent, you will need to add a background to BackgroundView. The standard backgrounds are:

android:background="@android:color/background_light"
android:background="@android:color/background_dark"

front_activity.xml

<?xml version="1.0" encoding="utf-8"?>

<!-- This is BackgroundView and can be any ViewGroup -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="@android:color/background_light" >

    <android.support.v7.widget.Toolbar
        android:layout_height="@dimen/height_toolbar"
        android:layout_width="match_parent"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

    <!-- rest of layout -->

</FrameLayout>

That's it. The animation should be working now.


EDIT

I have found a solution that doesn't flicker. The animation looks flawless.

When closing FrontActivity, call finish instead of NavUtils.navigateUpFromSameTask(activity). I have changed this in my answer.

like image 65
Robbe Avatar answered Sep 30 '22 12:09

Robbe


You can obtain the described behavior just overriding the transition between activities. I also include a fade-shrink effect on the back activity to improve its appearance:

slide_in_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="100%p" android:toXDelta="0"
        android:duration="@android:integer/config_shortAnimTime"/>
</set>

slide_out_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="0" android:toXDelta="100%p"
        android:duration="@android:integer/config_shortAnimTime"/>
</set>

fade_back.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale android:duration="@android:integer/config_shortAnimTime"
        android:pivotX="50.0%"
        android:pivotY="50.0%"
        android:fromXScale="1.0"
        android:toXScale="0.9"
        android:fromYScale="1.0"
        android:toYScale="0.9"/>
    <alpha android:duration="@android:integer/config_shortAnimTime"
        android:fromAlpha="1.0"
        android:toAlpha="0.7"/>
</set>

fade_forward.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale android:duration="@android:integer/config_shortAnimTime"
        android:pivotX="50.0%"
        android:pivotY="50.0%"
        android:fromXScale="0.9"
        android:toXScale="1.0"
        android:fromYScale="0.9"
        android:toYScale="1.0"/>
    <alpha android:duration="@android:integer/config_shortAnimTime"
        android:fromAlpha="0.7"
        android:toAlpha="1.0"/>
</set>

ParentActivity.java

In a parent class common for your activities you can include your reusable code:

/* Activity transitions */

protected void slideInTransition() {
    overridePendingTransition(R.anim.slide_in_right, R.anim.fade_back);
}

protected void slideOutTransition() {
    overridePendingTransition(R.anim.fade_forward, R.anim.slide_out_right);
}

Then on Activity Start:

startActivity(intent);
slideInTransition();

For back transition:

@Override
public void onBackPressed() {
    super.onBackPressed();
    slideOutTransition();
}
like image 27
AlexGuti Avatar answered Sep 30 '22 12:09

AlexGuti