Floating Action Button Speed Dial

Android library providing an implementation of the Material Design Floating Action Button Speed Dial.

Floating-Action-Button-Speed-Dial

Features

  • [x] MinSdk 14
  • [x] Highly customizable (label, icon, ripple, fab and label background colors, themes support)
  • [x] Same animations as in Inbox by Gmail
  • [x] Option to have different icons for open/close state
  • [x] Optional overlay/touch guard layout
  • [x] Support for bottom, left and right menu expansion (left and right have no labels)
  • [x] Out-of-the box support for Snackbar behavior
  • [x] Optional support for RecyclerView and NestedScrollView behavior
  • [x] Support for VectorDrawable
  • [x] Easy to use

Development status

Check the Waffle.io board.

How to use

Gradle setup

Official releases

The library is available on Jcenter so no additonal repository is required.

Dependencies entry (latest version on Jcenter Maven metadata URI):

implementation "com.leinardi.android:speed-dial:1.0-alpha06"

Snapshots (development branch)

You can use JitPack to test the latest master (remember that master is the development branch and can be unstable or completely broken).

Add the JitPack repository to your build file:

maven { url 'https://jitpack.io' }

Add the dependency

implementation 'com.github.leinardi:FloatingActionButtonSpeedDial:master-SNAPSHOT'

Basic use

SpeedDialView

Add the SpeedDialView to your layout:

<com.leinardi.android.speeddial.SpeedDialView
    android:id="@+id/speedDial"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    app:sdMainFabClosedSrc="@drawable/ic_add_white_24dp" />

Action items

Add the items to the SpeedDialView:

SpeedDialView speedDialView = findViewById(R.id.speedDial);
speedDialView.addActionItem(
        new SpeedDialActionItem.Builder(R.id.fab_link, R.drawable.ic_link_white_24dp)
                .create()
);

If the color customization is not requested, it is also possible to inflate the Action items
form a Menu Resource:

speedDialView.inflate(R.menu.menu_speed_dial);

Only the attributes android:id, android:icon and android:title are supported.

Click listeners

Add the click listeners:

speedDialView.setOnActionSelectedListener(new SpeedDialView.OnActionSelectedListener() {
    @Override
    public boolean onActionSelected(SpeedDialActionItem speedDialActionItem) {
        switch (speedDialActionItem.getId()) {
            case R.id.fab_link:
                showToast("Link action clicked!");
                return false; // true to keep the Speed Dial open
            default:
                return false;
        }
    }
});

Optional steps

Add the main action click listener

speedDialView.setOnChangeListener(new SpeedDialView.OnChangeListener() {
    @Override
    public void onMainActionSelected() {
        // Call your main action here
        return false; // true to keep the Speed Dial open
    }

    @Override
    public void onToggleChanged(boolean isOpen) {
        Log.d(TAG, "Speed dial toggle state changed. Open = " + isOpen);
    }
});

Customizing the items

The SpeedDialActionItem.Builder provides several setters to customize the aspect of one item:

mSpeedDialView.addActionItem(
        new SpeedDialActionItem.Builder(R.id.fab_custom_color, R.drawable.ic_custom_color)
                .setFabBackgroundColor(ResourcesCompat.getColor(getResources(), R.color.material_white_1000, getTheme()))
                .setFabImageTintColor(ResourcesCompat.getColor(getResources(), R.color.inbox_primary, getTheme()))
                .setLabel(getString(R.string.label_custom_color))
                .setLabelColor(Color.WHITE)
                .setLabelBackgroundColor(ResourcesCompat.getColor(getResources(), R.color.inbox_primary, getTheme()))
                .setLabelClickable(false)
                .create()
);

Is is also possible to specify a theme to easily change the FAB background and ripple effect color:

mSpeedDialView.addActionItem(
        new SpeedDialActionItem.Builder(R.id.fab_custom_theme, R.drawable.ic_theme_white_24dp)
                .setLabel(getString(R.string.label_custom_theme))
                .setTheme(R.style.AppTheme_Purple)
                .create());
<style name="AppTheme.Purple" parent="AppTheme">
    <item name="colorPrimary">@color/material_purple_500</item>
    <item name="colorPrimaryDark">@color/material_purple_700</item>
    <item name="colorAccent">@color/material_purple_a700</item>
    <item name="colorControlHighlight">@color/material_purple_200</item>
</style>

Adding an overlay/touch guard when the menu is open (like Inbox by Gmail)

You simply need to add the SpeedDialOverlayLayout to your layout:

<com.leinardi.android.speeddial.SpeedDialOverlayLayout
    android:id="@+id/overlay"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

and then provide the instance of that layout to the SpeedDialView:

<com.leinardi.android.speeddial.SpeedDialView
    android:id="@+id/speedDial"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:sdMainFabClosedSrc="@drawable/ic_add_white_24dp"
    app:sdOverlayLayout="@id/overlay" />

or

SpeedDialOverlayLayout overlayLayout = findViewById(R.id.overlay);
mSpeedDialView.setSpeedDialOverlayLayout(overlayLayout);

Hiding the FAB when scrolling a RecyclerView or a NestedScrollView

Just apply the ScrollingViewSnackbarBehavior to the SpeedDialView. This can be done via XML using
the convenience string resource @string/speeddial_scrolling_view_snackbar_behavior:

<com.leinardi.android.speeddial.SpeedDialView
    android:id="@+id/speedDial"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_behavior="@string/speeddial_scrolling_view_snackbar_behavior" />

Or programmatically:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) speedDialView.getLayoutParams();
params.setBehavior(new SpeedDialView.ScrollingViewSnackbarBehavior());
speedDialView.requestLayout();

NB: for the behaviors to work, SpeedDialView needs to be a direct child of CoordinatorLayout

Disabling SnackbarBehavior

Since the SnackbarBehavior is enabled by default and, afaik, it is not possible to remove a Behavior, simply use apply the SpeedDialView.NoBehavior instead:

CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) speedDialView.getLayoutParams();
params.setBehavior(new SpeedDialView.NoBehavior());
speedDialView.requestLayout();

GitHub