Search code examples
androidlayoutfloating-action-buttonandroid-bottomappbar

FAB isn't floating


The activity layout is a bit complex... it's a fragment activity, the bottom fragment ('bottomBarFragmentPlaceholder') is the bottomAppBar where the FAB is placed in the middle.

The activity layout is as follows:

<?xml version="1.0" encoding="utf-8"?><!-- practice_activity.xml -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ProgressBar
                android:id="@+id/progressBar"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignTop="@id/progressBarTimeText"
                android:layout_alignBottom="@id/progressBarTimeText"
                android:scaleY="6" />

            <TextView
                android:id="@+id/progressBarTimeText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:background="#00000000"
                android:gravity="center" />
        </RelativeLayout>

        <androidx.viewpager.widget.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/pager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />

        <FrameLayout
            android:id="@+id/bottomBarFragmentPlaceholder"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

</FrameLayout>

Then the BottomAppBar layout is as follows:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/bottomBarLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="false">

    <com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="@color/primaryLightColor"
        android:backgroundTint="@color/primaryLightColor"
        app:fabAlignmentMode="center"
        app:menu="@drawable/ic_action_overflow"
        app:navigationIcon="@drawable/ic_menu_24"
        app:popupTheme="@style/ThemeOverlay.MaterialComponents.Dark"
        app:theme="@style/ThemeOverlay.MaterialComponents.ActionBar" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@drawable/baseline_publish_black_24dp"
            app:layout_anchor="@id/bar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

And the outcome is:

Why is my FAB being pushed down instead of fitting into the cradle?

Any help would be very much appreciated.

thanks, GBa.


Solution

  • Well, played around with the different layouts until I finally got it all set...

    Key insights:

    • The FrameLayout which is required to allow overlay capabilities (floating button) is not needed in the upper levels but only in the lowest possible level... (see updated layouts below)

    • The bottomAppBar layout cannot be with layout_height="wrap_content", it needs to be given the ability to take all space of the parent... ("match_parent"), that's how the FAB will be given enough height to be placed correctly in the cradle.

    Finally, here are the updated layouts:

    The Fragment Activity layout is as follows:

    <?xml version="1.0" encoding="utf-8"?><!-- practice_activity.xml -->
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <ProgressBar
                android:id="@+id/progressBar"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignTop="@id/progressBarTimeText"
                android:layout_alignBottom="@id/progressBarTimeText"
                android:scaleY="6" />
    
            <TextView
                android:id="@+id/progressBarTimeText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:background="#00000000"
                android:gravity="center" />
        </RelativeLayout>
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <androidx.viewpager.widget.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/pager"
                android:layout_width="match_parent"
                android:layout_gravity="center|fill_vertical"
                android:layout_height="match_parent" />
    
            <FrameLayout
                android:id="@+id/bottomBarFragmentPlaceholder"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="bottom"/>
        </FrameLayout>
    </LinearLayout>
    

    The BottomAppBar layout is as follows:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/bottomBarLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="false">
    
        <com.google.android.material.bottomappbar.BottomAppBar
            android:id="@+id/bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:background="@color/primaryLightColor"
            android:backgroundTint="@color/primaryLightColor"
            app:fabAlignmentMode="center"
            app:menu="@drawable/ic_action_overflow"
            app:navigationIcon="@drawable/ic_menu_24"
            app:popupTheme="@style/ThemeOverlay.MaterialComponents.Dark"
            app:theme="@style/ThemeOverlay.MaterialComponents.ActionBar" />
    
            <com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/fab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/baseline_publish_black_24dp"
                app:layout_anchor="@id/bar" />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    I hope that this helps others that will face similar issues in the future...

    Happy coding... GBa.