androidkotlinorientationfloating-action-buttononconfigurationchanged

Change clans fab menu orientation programmatically


I am using clans fab library to create a menu with a set of buttons.

My menu fab as an open direction set to "up", and this works pretty fine if the phone is in portait mode. However if I turn it to landscape mode, half the buttons get cropped.

I was wondering if I could change the fab menu open orientation programmatically on my onConfigurationChanged method.

Something like this:

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        // set menu fab orientation to start|left
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        // set menu fab orientation to up
    }
}

I can't seem to find the method to change this programmatically. Does someone knows how to do it?


Solution

  • Unfortunately the Floating Action Menu currently supports only up and down for its open direction.

    Option to expand menu up and down

    There is also currently no option to change the configured direction programmatically: it is set in the XML.

    Adding the option to lay out the buttons horizontally would require significant changes to the library since the measurement and layout routines are not set up to handle this case.

    Recommendation

    Given that the labels would be laid out top-to-bottom when the menu is presented horizontally, your user experience would be negatively impacted anyway. Also, a large number of menu items in a way defeats the design intention of the FAB in the first place.

    A floating action button represents the primary action in an application. A floating action button is used for a promoted action.

    Given all that, I would strongly recommend that you rethink your approach, and limit the number of items you are adding to the FAB menu so that the items fit in both directions. Move the items that don't fit to the options menu or to a well-placed contextual popup menu.

    As a side note, clans' repo is end of life. I don't know who is going to take it over, but it's current status is a risk.

    Handling Config Changes

    One runs into situations where a repo doesn't allow programmatic changes based on configuration, but there is a way around that: use configuration-based fragments to accomplish the same result. For example:

    res/layout/activity_main.xml

    <?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"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.fabmenu.MainActivity">
    
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>
    
        </android.support.design.widget.AppBarLayout>
    
        <include layout="@layout/content_main"/>
    
        <!-- Replace the FAB with a fragment reference -->
        <include layout="@layout/fragment_fab_menu"/>
    
    </android.support.design.widget.CoordinatorLayout>
    

    Now we create two files, one for portrait and one for landscape:

    res/layout/fragment_fab_portrait.xml

    <?xml version="1.0" encoding="utf-8"?>
    <com.github.clans.fab.FloatingActionMenu
        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"
        ...    
        app:menu_openDirection="left"
        >
    
        <com.github.clans.fab.FloatingActionButton
            android:id="@+id/menu_item_horse"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/fab_add"
            app:fab_colorNormal="@color/colorAccent"
            app:fab_label="Horse"
            app:fab_size="mini"/>
    
        ...
    
    </com.github.clans.fab.FloatingActionMenu>
    

    res/layout/fragment_fab_landscape.xml (Note: 'left' is fictional in this case.)

    <?xml version="1.0" encoding="utf-8"?>
    <com.github.clans.fab.FloatingActionMenu
        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"
        ...    
        app:menu_openDirection="left"
        >
    
        <com.github.clans.fab.FloatingActionButton
            android:id="@+id/menu_item_horse"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/fab_add"
            app:fab_colorNormal="@color/colorAccent"
            app:fab_label="Horse"
            app:fab_size="mini"/>
    
        ...
    
    </com.github.clans.fab.FloatingActionMenu>
    

    The only differences between these two files are the layout changes we need based on configuration.

    Now we add the magic to pull it all together. Two files to let Android know which file to pick.

    /res/values/layouts.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <item name="fragment_fab_menu" type="layout">@layout/fragment_fab_portrait</item>
    </resources>
    

    /res/values/layouts-land.xml

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <!-- Here name refers to the id we gave it in activity_main.xml -->
        <item name="fragment_fab_menu" type="layout">@layout/fragment_fab_landscape</item>
    </resources>
    

    For more information see Supporting Different Screen Sizes