Floating Action MENU – No 3rd Party Library – Quick Tutorial (Xamarin Android) (Code)

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>

 

About the author 

Matt Rešetár

Matt is an app developer with a knack for teaching others. Working as a freelancer and most importantly developer educator, he is set on helping other people succeed in their Flutter app development career.

You may also like

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
    >