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
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
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.
You can dock a FloatingActionButton by specifying floatingActionButtonLocation in a Scaffold and using BottomAppBar .
Question is old, however it is still interesting. That's how I implemented this:
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With