에몽이

Floating Button With animation 본문

android

Floating Button With animation

ian_hodge 2017. 8. 24. 17:52


Ever since Material design inception Floating Action Button is one of the most important component of this awesome design language. Also Google made it easier to implement FAB in our Android app with the help of the Design Support Library which was released following Google I/O 2015. Adding FAB is very simple which is similar to Button or other widgets. In this article we are going to see how to implement a simple FAB open/close animation. Take a look at the animation given below to get an idea what we are going to do.

fab1

Creating Project

Here i have created a Android Studio project with package learn2crack.fabanimation also Activity as MainActivity and layout as activity_main.

Complete Project Files

You can download the complete project as zip or fork from our Github repository.

Creating Layout

Material Design Icons

We have a larger FAB and two smaller FAB. When the larger FAB is pressed the two smaller FAB pop up. Initially the two smaller Fab are invisible.The layout activity_main is given as,

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="160dp"
        android:layout_gravity="bottom|end"
        android:layout_marginRight="@dimen/fab_margin"
        android:visibility="invisible"
        app:backgroundTint="@color/colorFAB2"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp"
        android:src="@drawable/ic_done" />
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="90dp"
        android:layout_gravity="bottom|end"
        android:layout_marginRight="@dimen/fab_margin"
        android:visibility="invisible"
        app:elevation="6dp"
        app:backgroundTint="@color/colorFAB1"
        app:pressedTranslationZ="12dp"
        android:src="@drawable/ic_message" />
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        app:elevation="6dp"
        app:backgroundTint="@color/colorAccent"
        app:pressedTranslationZ="12dp"
        android:layout_margin="@dimen/fab_margin"
        android:src="@drawable/ic_add" />

</android.support.design.widget.CoordinatorLayout>

The colors I used are,

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#4CAF50</color>
    <color name="colorPrimaryDark">#388E3C</color>
    <color name="colorAccent">#F44336</color>
    <color name="colorFAB1">#2196F3</color>
    <color name="colorFAB2">#E040FB</color>
</resources>

Defining Animation

Our project has four animations. They are,

1. fab_open
2. fab_close
3. rotate_forward
4. rotate_backward

The defined animations are placed in res/anim folder as xml. Let us now discuss what these four animations does

fab_open

Initially the two smaller FAB are invisible and not clickable. When the larger FAB with Add icon is pressed the two smaller FAB scale from their invisible initial position and at the same time opacity increases. These two are achieved by using the <scale>and <alpha> animation elements.

fab_open.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">
    <scale
        android:duration="300"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXScale="0.8"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toYScale="0.8" />
    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:duration="300"/>
</set>

fab_close

This the exact opposite of the fab_open animation. The two smaller FAB dissappers to its original state.

fab_close.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">
    <scale
        android:duration="300"
        android:fromXScale="0.8"
        android:fromYScale="0.8"
        android:interpolator="@android:anim/linear_interpolator"
        android:toXScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toYScale="0.0" />
    <alpha android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:duration="300"/>
</set>

rotate_forward

In the above animation you have noted that when the large Add FAB is pressed the icon in the Add FAB rotates to 45 degrees to become Close FAB. This can be achieved by rotating the larger FAB by 45 degrees.

img1

rotate_forward.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" >
    <rotate android:fromDegrees="0"
        android:toDegrees="45"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="300"
        android:interpolator="@android:anim/linear_interpolator"/>
</set>

rotate_backward

This is the exact reverse of the rotate_forward animation. The larger FAB rotates back to its original position.

img2

rotate_backward.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true" >
    <rotate android:fromDegrees="45"
        android:toDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="300"
        android:interpolator="@android:anim/linear_interpolator"/>
</set>

All the four animations have the duration of 300ms. If you want to reduce or increase the duration change the duration property.

Creating Activity Class

Initailly we load the defined xml animations using AnimationUtils.loadAnimation() method. We implement a OnClickListenerinterface to our MainActivity. We define a boolean variable isFabOpen to check the FAB is opened or closed (i.e The initial position when the small FAB are invisible is closed position and the position in which the small FAB are visible is open position). The animation is started using the startAnimation() method. When the larger FAB is pressed the animateFAB()method is called which is defined as

    public void animateFAB(){

        if(isFabOpen){

            fab.startAnimation(rotate_backward);
            fab1.startAnimation(fab_close);
            fab2.startAnimation(fab_close);
            fab1.setClickable(false);
            fab2.setClickable(false);
            isFabOpen = false;
            Log.d("Raj", "close");

        } else {

            fab.startAnimation(rotate_forward);
            fab1.startAnimation(fab_open);
            fab2.startAnimation(fab_open);
            fab1.setClickable(true);
            fab2.setClickable(true);
            isFabOpen = true;
            Log.d("Raj","open");

        }
    }

The complete MainActivity.java class is given by,

MainActivity.java

package learn2crack.fabanimation;

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Boolean isFabOpen = false;
    private FloatingActionButton fab,fab1,fab2;
    private Animation fab_open,fab_close,rotate_forward,rotate_backward;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        fab = (FloatingActionButton)findViewById(R.id.fab);
        fab1 = (FloatingActionButton)findViewById(R.id.fab1);
        fab2 = (FloatingActionButton)findViewById(R.id.fab2);
        fab_open = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fab_open);
        fab_close = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fab_close);
        rotate_forward = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.rotate_forward);
        rotate_backward = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.rotate_backward);
        fab.setOnClickListener(this);
        fab1.setOnClickListener(this);
        fab2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id){
            case R.id.fab:

                animateFAB();
                break;
            case R.id.fab1:

                Log.d("Raj", "Fab 1");
                break;
            case R.id.fab2:

                Log.d("Raj", "Fab 2");
                break;
        }
    }

    public void animateFAB(){

        if(isFabOpen){

            fab.startAnimation(rotate_backward);
            fab1.startAnimation(fab_close);
            fab2.startAnimation(fab_close);
            fab1.setClickable(false);
            fab2.setClickable(false);
            isFabOpen = false;
            Log.d("Raj", "close");

        } else {

            fab.startAnimation(rotate_forward);
            fab1.startAnimation(fab_open);
            fab2.startAnimation(fab_open);
            fab1.setClickable(true);
            fab2.setClickable(true);
            isFabOpen = true;
            Log.d("Raj","open");

        }
    }
}

Screenshots

Happy Coding 🙂

https://www.learn2crack.com/2015/10/android-floating-action-button-animations.html


Comments