Skip to content

Instantly share code, notes, and snippets.

@chris95x8
Created December 13, 2014 22:35
Show Gist options
  • Star 53 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save chris95x8/882b5c5d0aa2096236ba to your computer and use it in GitHub Desktop.
Save chris95x8/882b5c5d0aa2096236ba to your computer and use it in GitHub Desktop.
FAB expand
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="88dp"
android:layout_gravity="bottom"
android:orientation="vertical">
<ImageButton
android:id="@+id/fab"
android:layout_width="@dimen/fab_size"
android:layout_height="@dimen/fab_size"
android:layout_gravity="bottom|right"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:background="@drawable/ripple"
android:elevation="8dp"
android:src="@drawable/ic_add"
android:stateListAnimator="@anim/fab_raise"
android:tint="@color/primary_dark" />
<RelativeLayout
android:id="@+id/expanded_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/accent"
android:orientation="horizontal"
android:padding="16dp"
android:visibility="invisible">
<ImageButton
android:id="@+id/act_collapse"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_alignParentRight="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_add"
android:tint="@color/primary_dark" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toLeftOf="@+id/act_collapse"
android:orientation="horizontal">
<ImageButton
android:id="@+id/btn_action_1"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_action"
android:tint="@color/primary_dark" />
<ImageButton
android:id="@+id/btn_action_2"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_action"
android:tint="@color/primary_dark" />
<ImageButton
android:id="@+id/btn_action_3"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_action"
android:tint="@color/primary_dark" />
<ImageButton
android:id="@+id/btn_action_4"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_action"
android:tint="@color/primary_dark" />
</LinearLayout>
</RelativeLayout>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/fab_actions"/>
</FrameLayout>
package com.materialdesign.chris.materialdesignexperimenting;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.Interpolator;
/**
* Created by Chris Basha on 14/12/2014.
*/
public class UIActivity extends Activity {
public static final int FAB_STATE_COLLAPSED = 0;
public static final int FAB_STATE_EXPANDED = 1;
public static int FAB_CURRENT_STATE = FAB_STATE_COLLAPSED;
View mFab, mExpandedView, mCollapseFabButton;
View act1, act2, act3, act4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
mFab = findViewById(R.id.fab);
mExpandedView = findViewById(R.id.expanded_view);
mCollapseFabButton = findViewById(R.id.act_collapse);
act1 = findViewById(R.id.btn_action_1);
act2 = findViewById(R.id.btn_action_2);
act3 = findViewById(R.id.btn_action_3);
act4 = findViewById(R.id.btn_action_4);
mFab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
revealView(mExpandedView);
FAB_CURRENT_STATE = FAB_STATE_EXPANDED;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mFab.setVisibility(View.GONE);
}
}, 50);
mCollapseFabButton.animate().rotationBy(135).setDuration(250).start();
}
});
mCollapseFabButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
hideView(mExpandedView);
FAB_CURRENT_STATE = FAB_STATE_COLLAPSED;
mCollapseFabButton.animate().rotationBy(-135).setDuration(200).start();
}
});
}
public void revealView(View myView) {
int cx = (mFab.getLeft() + mFab.getRight()) / 2;
int cy = (mFab.getTop() + mFab.getBottom()) / 2;
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
anim.setDuration(300);
myView.setVisibility(View.VISIBLE);
slideView(act1);
slideView(act2);
slideView(act3);
slideView(act4);
anim.start();
}
public void hideView(final View myView) {
int cx = (mFab.getLeft() + mFab.getRight()) / 2;
int cy = (mFab.getTop() + mFab.getBottom()) / 2;
int initialRadius = myView.getWidth();
Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
anim.setDuration(300);
anim.setInterpolator(getLinearOutSlowInInterpolator());
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
//Normally I would restore visibility when the hide animation has ended, but it doesn't look as good, so I'm doing it earlier.
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mFab.setVisibility(View.VISIBLE);
}
}, 200);
anim.start();
}
//Animation to slide the action buttons
public void slideView(View view) {
ObjectAnimator slide = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, 112, 0);
slide.setDuration(500);
slide.setInterpolator(getLinearOutSlowInInterpolator());
slide.start();
}
//Code for these: https://gist.github.com/chris95x8/4d74591bed75fd151799
public static Interpolator getLinearOutSlowInInterpolator() {
//Decelerate Interpolator - For elements that enter the screen
return new CubicBezierInterpolator(0, 0, 0.2, 1);
}
public static Interpolator getFastInSlowOutInterpolator() {
//Ease In Out Interpolator - For elements that change position while staying in the screen
return new CubicBezierInterpolator(0.4, 0, 0.2, 1);
}
}
@JonathanNakhla
Copy link

Hey Chris! I just stumbled upon this while Googling for something specific. Is this code for pressing a FAB which would then expand a View?

@BapNesS
Copy link

BapNesS commented Feb 9, 2015

Great piece of code. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment