Arrange a BottomNavigationView, a FAB, and a FrameLayout in a CoordinatorLayout and make it work with Snackbar

Viewed 883

I want to place a FrameLayout for hosting Fragments, a BottomNavigationView and a FAB inside a CoordinatorLayout. I would like to display a Snackbar over the BottomNavigationView and FAB to move up and down to accommodate the Snackbar. I have come up with the following layout but I am unable to get Snackbar and FAB behavior correctly.

<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".landingpage.MainActivity">

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <androidx.appcompat.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" />
</com.google.android.material.appbar.AppBarLayout>

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/content_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <FrameLayout
        android:id="@+id/fragment_cont"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/bottom_main_activity_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>

<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
    android:id="@+id/extended_fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom|end"
    android:layout_marginEnd="16dp"
    android:layout_marginBottom="72dp"
    android:contentDescription="@string/cont_desc"
    android:text="@string/chat"
    app:icon="@drawable/ic_baseline_chat_24" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

If I set LayoutParams like in this post then that margin 72dp margin is also displayed throwing FAB way up in the layout. If I don't use the margin the FAB will be stacked over the BottomNavigationView. I can use addCallback to set FAB margins programattically. Then also it will jump and then align itself to the right position. Overall it is not a good experience UX wise.

1 Answers

I would like to display a Snackbar over the BottomNavigationView and FAB to move up and down to accommodate the Snackbar. I have come up with the following layout but I am unable to get Snackbar and FAB behavior correctly.

You get a bad behavior because you're trying to achieve something which is not common or maybe, not implemented this way by using BottomNavigationView and FAB together. It's actually more common to use FAB & BottomAppBar at the bottom of a layout.


Then also it will jump and then align itself to the right position. Overall it is not a good experience UX wise.

Although it's not a good experience for users from a UX view, however, here are the approaches I may suggest:

Best approach : Using another CoordinatorLayout inside LinearLayout (Supported the FAB animation):

enter image description here

Code:

<?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/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:title="Test" />
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/content_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

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

    </androidx.core.widget.NestedScrollView>

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

        <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:id="@+id/SnackBar"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
                android:id="@+id/extended_fab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|end"
                android:layout_margin="16dp"
                android:text="Chat"
                android:textColor="@color/white"
                app:icon="@drawable/ic_baseline_send_24"
                app:iconTint="@color/white" />

        </androidx.coordinatorlayout.widget.CoordinatorLayout>

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            app:layout_insetEdge="bottom"
            app:menu="@menu/escrow_menu" />
    </LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

And in Kotlin side:

extended_fab.setOnClickListener {

            val snack: Snackbar = Snackbar.make(SnackBar, " Successfully ...!", Snackbar.LENGTH_SHORT)
            snack.show()
        }

2. BottomAppBar & FAB & setAnchorView() method without FAB animation

  • Anchored to FAB

enter image description here

Code:

<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/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <androidx.core.widget.NestedScrollView
        android:id="@+id/content_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!-- your FrameLayout maybe -->

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|center"
            android:text="SHOW SnakeBar"
            app:layout_anchor="@+id/content_layout"
            app:layout_anchorGravity="center" />


    </androidx.core.widget.NestedScrollView>

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:title="Test" />
    </com.google.android.material.appbar.AppBarLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:focusable="true"
        app:layout_anchor="@id/bar" />

    <com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:layout_gravity="bottom"
        android:backgroundTint="@color/colorPrimaryDark">

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

            <TextView
                style="?android:attr/borderlessButtonStyle"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="?android:attr/selectableItemBackground"
                android:drawableTop="@drawable/ic_baseline_send_24"
                android:gravity="center"
                android:orientation="vertical"
                android:text="Personal"
                android:textColor="#FFFFFF">

            </TextView>

            <TextView
                style="?android:attr/borderlessButtonStyle"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="?android:attr/selectableItemBackground"
                android:drawableTop="@drawable/ic_baseline_send_24"
                android:gravity="center"
                android:orientation="vertical"
                android:text="Personal"
                android:textColor="#FFFFFF">

            </TextView>

            <TextView
                style="?android:attr/borderlessButtonStyle"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="?android:attr/selectableItemBackground"
                android:drawableTop="@drawable/ic_baseline_send_24"
                android:gravity="center"
                android:orientation="vertical"
                android:textColor="#FFFFFF"
                android:visibility="invisible">

            </TextView>

            <TextView
                style="?android:attr/borderlessButtonStyle"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="?android:attr/selectableItemBackground"
                android:drawableTop="@drawable/ic_baseline_send_24"
                android:gravity="center"
                android:orientation="vertical"
                android:text="Personal"
                android:textColor="#FFFFFF">

            </TextView>

            <TextView
                style="?android:attr/borderlessButtonStyle"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:background="?android:attr/selectableItemBackground"
                android:drawableTop="@drawable/ic_baseline_send_24"
                android:gravity="center"
                android:orientation="vertical"
                android:text="Personal"
                android:textColor="#FFFFFF">

            </TextView>

        </LinearLayout>

    </com.google.android.material.bottomappbar.BottomAppBar>


</androidx.coordinatorlayout.widget.CoordinatorLayout>

3. Using FAB - BottomNavigationView - ConstraintLayout without FAB animation

enter image description here

Code:

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floating_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end"
        android:layout_margin="16dp"
        app:backgroundTint="@color/colorPrimary"
        app:elevation="10dp"
        app:layout_constraintBottom_toTopOf="@id/navigation"
        app:layout_constraintLeft_toRightOf="@id/navigation"
        app:layout_constraintRight_toLeftOf="@id/navigation"
        app:layout_constraintTop_toBottomOf="@id/navigation"
        app:layout_constraintTop_toTopOf="@id/navigation"
        app:layout_insetEdge="bottom" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/colorPrimaryDark"
        android:visibility="visible"
        app:itemIconTint="@color/white"
        app:itemTextColor="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/escrow_menu" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="290dp"
        android:layout_marginBottom="485dp"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Related