Floating action button aka FAB is a staple of apps using material design. What if you need the user to choose from multiple different actions? Well, you have to use a floating action menu which is basically a FAB which upon click displays multiple smaller FABs.
There are two ways in which we can add a floating action menu. Using a 3rd party library is one option, but that is not always ideal because libraries can get outdated. Much more viable option is to code it ourselves and use the latest and greatest things from the design support library made by Google which guarantees we will always be able to use bleeding edge features.
This post contains all the code that’s been written in this YouTube video.
You can also check out this GitHub repository: https://github.com/ResoCoder/FabMenuXamarinAndroid
MainActivity.cs
using Android.App; using Android.Widget; using Android.OS; using Android.Support.V7.App; using Android.Support.Design.Widget; using Android.Views; using System; using Android.Animation; namespace FabMenuTut { [Activity(Label = "FabMenuTut", MainLauncher = true)] public class MainActivity : AppCompatActivity { private static bool isFabOpen; private FloatingActionButton fabAirballoon; private FloatingActionButton fabCake; private FloatingActionButton fabMain; private View bgFabMenu; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.Main); fabAirballoon = FindViewById<FloatingActionButton>(Resource.Id.fab_airballoon); fabCake = FindViewById<FloatingActionButton>(Resource.Id.fab_cake); fabMain = FindViewById<FloatingActionButton>(Resource.Id.fab_main); bgFabMenu = FindViewById<View>(Resource.Id.bg_fab_menu); fabMain.Click += (o, e) => { if (!isFabOpen) ShowFabMenu(); else CloseFabMenu(); }; fabCake.Click += (o, e) => { CloseFabMenu(); Toast.MakeText(this, "Cake!", ToastLength.Short).Show(); }; fabAirballoon.Click += (o, e) => { CloseFabMenu(); Toast.MakeText(this, "Airballoon!", ToastLength.Short).Show(); }; bgFabMenu.Click += (o, e) => CloseFabMenu(); } private void ShowFabMenu() { isFabOpen = true; fabAirballoon.Visibility = ViewStates.Visible; fabCake.Visibility = ViewStates.Visible; bgFabMenu.Visibility = ViewStates.Visible; fabMain.Animate().Rotation(135f); bgFabMenu.Animate().Alpha(1f); fabAirballoon.Animate() .TranslationY(-Resources.GetDimension(Resource.Dimension.standard_100)) .Rotation(0f); fabCake.Animate() .TranslationY(-Resources.GetDimension(Resource.Dimension.standard_55)) .Rotation(0f); } private void CloseFabMenu() { isFabOpen = false; fabMain.Animate().Rotation(0f); bgFabMenu.Animate().Alpha(0f); fabAirballoon.Animate() .TranslationY(0f) .Rotation(90f); fabCake.Animate() .TranslationY(0f) .Rotation(90f).SetListener(new FabAnimatorListener(bgFabMenu, fabCake, fabAirballoon)); } private class FabAnimatorListener : Java.Lang.Object, Animator.IAnimatorListener { View[] viewsToHide; public FabAnimatorListener(params View[] viewsToHide) { this.viewsToHide = viewsToHide; } public void OnAnimationCancel(Animator animation) { } public void OnAnimationEnd(Animator animation) { if (!isFabOpen) foreach (var view in viewsToHide) view.Visibility = ViewStates.Gone; } public void OnAnimationRepeat(Animator animation) { } public void OnAnimationStart(Animator animation) { } } } }
Main.axml
<?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" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Hello FAB menu!" android:textSize="24sp"/> <View android:id="@+id/bg_fab_menu" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#48000000" android:alpha="0" android:visibility="gone"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab_airballoon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/standard_23" android:visibility="gone" android:rotation="90" app:fabSize="mini" app:srcCompat="@drawable/ic_airballoon"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab_cake" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/standard_23" android:visibility="gone" android:rotation="90" app:fabSize="mini" app:srcCompat="@drawable/ic_cake"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" app:fabSize="normal" app:srcCompat="@drawable/ic_plus"/> </android.support.design.widget.CoordinatorLayout>
dimens.xml
<resources> <dimen name="fab_margin">16dp</dimen> <dimen name="standard_12">12dp</dimen> <dimen name="standard_23">23dp</dimen> <dimen name="standard_55">55dp</dimen> <dimen name="standard_100">100dp</dimen> <dimen name="standard_145">145dp</dimen> </resources>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="FabMenuTut.FabMenuTut" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="21" /> <application android:allowBackup="true" android:label="@string/app_name" android:theme="@style/Theme.AppCompat.Light.DarkActionBar"> </application> </manifest>
thanks 🙂