Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate floating action button using android activity transition?

I am planning to implement something like this in one of my project but the concept for the following is unclear to me, there's no such tutorial available either, moreover you don't get to see this very often. Here is how it looks like Click here to go to source

enter image description here

From all the references what i have understood is they have used two types of transition here one to move the button upto some extant and another to explode the button. So i did some digging and came across with these two library in github i think with these two we can achieve the following animation here are the links

Material Animations (to move the button) and Circular reveal (to make the button looks like being exploded)

If you find any better answer to the following please post here please

like image 479
silverFoxA Avatar asked Apr 24 '15 11:04

silverFoxA


People also ask

How do you implement a floating action button?

Add the floating action button to your layoutThe size of the FAB, using the app:fabSize attribute or the setSize() method. The ripple color of the FAB, using the app:rippleColor attribute or the setRippleColor() method. The FAB icon, using the android:src attribute or the setImageDrawable() method.

Is Floating Action button docked?

You can dock a FloatingActionButton by specifying floatingActionButtonLocation in a Scaffold and using BottomAppBar .


1 Answers

Question is old, however it is still interesting. That's how I implemented this:

enter image description here

First of all you need to create two ViewGroups which in transition api are called "scenes". First scene contains views before transition, second one contain views after transition. Then you should just replace first scene with second one and provide Transition which describes how views from first scene goes to second scene, also how views in first scene disappear and how views in second scene appear.

enter image description here

In this example there is difficulty with fab button, because it is the only view which is animated out of white area of "scene root" screen. Thats why scenes are fullscreen with margin top which equals to height of blue "monday" header.

All transitions here are default except of yellow background transition. Yellow background view appears in second scene with circular reveal animation. And it dissapear with circular reveal collapse animation. There is no default animation like this, thats why I wrote custom one:

import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.support.transition.TransitionValues; import android.support.transition.Visibility; import android.view.View; import android.view.ViewAnimationUtils; import android.view.ViewGroup;  public class CircularRevealTransition extends Visibility {  @Override public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) {     int startRadius = 0;     int endRadius = (int) Math.hypot(view.getWidth(), view.getHeight());     Animator reveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, startRadius, endRadius);     //make view invisible until animation actually starts     view.setAlpha(0);     reveal.addListener(new AnimatorListenerAdapter() {         @Override         public void onAnimationStart(Animator animation) {             view.setAlpha(1);         }     });     return reveal; }  @Override public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) {     int endRadius = 0;     int startRadius = (int) Math.hypot(view.getWidth(), view.getHeight());     Animator reveal = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, startRadius, endRadius);     return reveal; } } 

Full code is here:

import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; import android.support.transition.ArcMotion; import android.support.transition.ChangeBounds; import android.support.transition.Fade; import android.support.transition.Scene; import android.support.transition.Slide; import android.support.transition.Transition; import android.support.transition.TransitionListenerAdapter; import android.support.transition.TransitionManager; import android.support.transition.TransitionSet; import android.support.v7.app.AppCompatActivity; import android.view.Gravity; import android.view.View; import android.view.ViewGroup;  public class MainActivity extends AppCompatActivity {      private ViewGroup mSceneRoot;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         setSupportActionBar(findViewById(R.id.toolbar));         mSceneRoot = findViewById(R.id.sceneRoot);         //show scene1 without animation         showScene1(false);     }      private void showScene1(boolean animated) {         ViewGroup root = (ViewGroup) getLayoutInflater().inflate(R.layout.scene1, null);         FloatingActionButton fab = root.findViewById(R.id.fab);         fab.setOnClickListener(v -> {             showScene2();         });         Scene scene = new Scene(mSceneRoot, root);         Transition transition = animated ? getScene1Transition() : null;         TransitionManager.go(scene, transition);     }      private void showScene2() {         ViewGroup root = (ViewGroup) getLayoutInflater().inflate(R.layout.scene2, null);         View btnBack = root.findViewById(R.id.btnCancel);         btnBack.setOnClickListener(v -> {             showScene1(true);         });          Scene scene = new Scene(mSceneRoot, root);         Transition transition = getScene2Transition();         TransitionManager.go(scene, transition);     }      private Transition getScene2Transition() {         TransitionSet set = new TransitionSet();          //fab changes position         ChangeBounds changeTransform = new ChangeBounds();         changeTransform.addListener(new TransitionListenerAdapter() {             @Override             public void onTransitionEnd(@NonNull Transition transition) {                 //hide fab button on the end of animation                 mSceneRoot.findViewById(R.id.fab).setVisibility(View.INVISIBLE);             }         });         changeTransform.addTarget(R.id.fab);         changeTransform.setDuration(300);         //fab arc path         ArcMotion arcMotion = new ArcMotion();         arcMotion.setMaximumAngle(45);         arcMotion.setMinimumHorizontalAngle(90);         arcMotion.setMinimumVerticalAngle(0);         changeTransform.setPathMotion(arcMotion);         set.addTransition(changeTransform);          //bg circular reveal animation starts         CircularRevealTransition crt = new CircularRevealTransition();         crt.addTarget(R.id.yellowBG);         crt.setStartDelay(200);         crt.setDuration(600);         set.addTransition(crt);          //buttons appear         Fade fade = new Fade();         fade.addTarget(R.id.btnBegin);         fade.addTarget(R.id.btnCancel);         fade.addTarget(R.id.text);         fade.setStartDelay(600);         set.addTransition(fade);          //left buttons column slide to left         Slide slide = new Slide(Gravity.LEFT);         slide.addTarget(R.id.slideLeftContainer);         set.addTransition(slide);         //right buttons column slide to right         Slide slide2 = new Slide(Gravity.RIGHT);         slide2.addTarget(R.id.slideRightContainer);         set.addTransition(slide2);         return set;     }      private Transition getScene1Transition() {         TransitionSet set = new TransitionSet();          //buttons from scene2 fade out         Fade fade = new Fade();         fade.addTarget(R.id.btnBegin);         fade.addTarget(R.id.btnCancel);         fade.addTarget(R.id.text);         set.addTransition(fade);          //Circular Reveal collapse animation starts         CircularRevealTransition crt = new CircularRevealTransition();         crt.addTarget(R.id.yellowBG);         crt.setDuration(600);         set.addTransition(crt);          //then fab button changes position         ChangeBounds changeTransform = new ChangeBounds();         changeTransform.addTarget(R.id.fab);         changeTransform.setDuration(300);         changeTransform.setStartDelay(500);         //arc path         ArcMotion arcMotion = new ArcMotion();         arcMotion.setMaximumAngle(45);         arcMotion.setMinimumHorizontalAngle(90);         arcMotion.setMinimumVerticalAngle(0);         changeTransform.setPathMotion(arcMotion);         set.addTransition(changeTransform);          //left buttons column slide in from left         Slide slide = new Slide(Gravity.LEFT);         slide.addTarget(R.id.slideLeftContainer);         slide.setStartDelay(500);         set.addTransition(slide);          //right buttons column slide in from right         Slide slide2 = new Slide(Gravity.RIGHT);         slide2.addTarget(R.id.slideRightContainer);         slide2.setStartDelay(500);         set.addTransition(slide2);         return set;     }  } 

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout  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" tools:context=".MainActivity">       <android.support.v7.widget.Toolbar     android:id="@+id/toolbar"     android:layout_width="match_parent"     android:layout_height="?attr/actionBarSize"     android:background="?attr/colorPrimary"     app:layout_constraintLeft_toLeftOf="parent"     app:layout_constraintRight_toRightOf="parent"     app:layout_constraintTop_toTopOf="parent"     app:titleTextColor="#fff" />      <FrameLayout     android:id="@+id/topContainer"     android:layout_width="match_parent"     android:layout_height="@dimen/header_height"     android:background="#00BCD4"     android:orientation="vertical"     app:layout_constraintLeft_toLeftOf="parent"     app:layout_constraintRight_toRightOf="parent"     app:layout_constraintTop_toBottomOf="@+id/toolbar">          <TextView         android:layout_width="match_parent"         android:layout_height="36dp"         android:layout_gravity="bottom"         android:background="#9000"         android:gravity="center_vertical"         android:paddingLeft="8dp"         android:text="MONDAY"         android:textColor="#fff" />     </FrameLayout>      <FrameLayout     android:id="@+id/sceneRoot"     android:layout_width="match_parent"     android:layout_height="0dp"     android:clipChildren="false"     android:clipToPadding="false"     app:layout_constraintBottom_toBottomOf="parent"     app:layout_constraintLeft_toLeftOf="parent"     app:layout_constraintRight_toRightOf="parent"     app:layout_constraintTop_toBottomOf="@+id/toolbar" />  </android.support.constraint.ConstraintLayout> 

scene1.xml:

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false">  <LinearLayout     android:id="@+id/slideLeftContainer"     android:layout_width="wrap_content"     android:layout_height="match_parent"     android:layout_marginTop="@dimen/header_height"     android:orientation="vertical">      <include layout="@layout/button" />     <include layout="@layout/button" />     <include layout="@layout/button" /> </LinearLayout>  <LinearLayout     android:id="@+id/slideRightContainer"     android:layout_width="wrap_content"     android:layout_height="match_parent"     android:layout_gravity="right"     android:layout_marginTop="@dimen/header_height"     android:orientation="vertical">      <include layout="@layout/button" />     <include layout="@layout/button" />     <include layout="@layout/button" /> </LinearLayout>  <android.support.design.widget.FloatingActionButton     android:id="@+id/fab"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_gravity="right"     android:layout_marginTop="@dimen/fab_margin_top"     android:layout_marginRight="@dimen/fab_margin"     android:clickable="true"     android:focusable="true"     app:backgroundTint="#FFEE4D"     app:srcCompat="@drawable/ic_add_black_24dp" /> </FrameLayout> 

scene2.xml:

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" android:paddingTop="@dimen/header_height">  <View     android:id="@+id/yellowBG"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:background="#FFEE4D" />  <android.support.design.widget.FloatingActionButton     android:id="@+id/fab"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_gravity="center"     android:layout_margin="@dimen/fab_margin"     app:backgroundTint="#FFEE4D"     app:srcCompat="@drawable/ic_add_black_24dp" />  <Button     android:id="@+id/btnBegin"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_gravity="bottom|left"     android:layout_margin="@dimen/fab_margin"     android:padding="16dp"     android:text="BEGIN"     android:textSize="22sp" />  <TextView     android:id="@+id/text"     android:layout_width="@dimen/header_height"     android:layout_height="wrap_content"     android:layout_gravity="center"     android:gravity="center"     android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt"     android:textSize="22sp" />  <Button     android:id="@+id/btnCancel"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_gravity="bottom|right"     android:layout_margin="@dimen/fab_margin"     android:backgroundTint="#FF5151"     android:padding="16dp"     android:text="CANCEL"     android:textSize="22sp" />  </FrameLayout> 

button.xml:

<?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_margin="16dp"     android:padding="24dp"     android:text="6:30"     android:textSize="24sp" /> 

values.xml:

<?xml version="1.0" encoding="utf-8"?> <resources>     <string name="app_name">TestTransition</string>      <color name="colorPrimary">#3F51B5</color>     <color name="colorPrimaryDark">#303F9F</color>     <color name="colorAccent">#FF4081</color>      <dimen name="fab_margin">16dp</dimen>     <dimen name="header_height">200dp</dimen>     <dimen name="fab_margin_top">132dp</dimen> </resources> 
like image 65
ashakirov Avatar answered Sep 20 '22 05:09

ashakirov