How to combine BottomAppBar + FAB with BottomNavigationView

后端 未结 6 1737
不知归路
不知归路 2020-11-30 00:29

I want to use the FloatingActionButton, along with its behaviour when anchored on a BottomAppBar, on top of a BottomNavigationView.

I came up with a rat

相关标签:
6条回答
  • 2020-11-30 01:10

    Well you can treat BottomAppBar as Toolbar, which means that, this class extends ViewGroup so you can add relative layout, constraint layout etc inside BottomAppBar tag. Here is fragment of code that will show 2 buttons inside BottomAppBar.

    <com.google.android.material.bottomappbar.BottomAppBar
            android:id="@+id/bar"
            style="@style/Widget.MaterialComponents.BottomAppBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            app:backgroundTint="@color/cardview_dark_background"
            app:fabAlignmentMode="center">
    
            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
                <Button
                    android:id="@+id/leftbutton"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_marginRight="32dp"
                    android:text="LEFT"
                    android:textColor="@android:color/white"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintRight_toLeftOf="@+id/rightbutton"
                    app:layout_constraintTop_toTopOf="parent" />
    
                <Button
                    android:id="@+id/rightbutton"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="32dp"
                    android:layout_marginRight="16dp"
                    android:text="RIGHT"
                    android:textColor="@android:color/white"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintLeft_toRightOf="@+id/leftbutton"
                    app:layout_constraintRight_toRightOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
            </androidx.constraintlayout.widget.ConstraintLayout>
        </com.google.android.material.bottomappbar.BottomAppBar>
    
    0 讨论(0)
  • 2020-11-30 01:14

    I tried to do this for several days and in the end I came to make a FAB with an empty BottomAppBar, on top of which a BottomNavigationView with a transparent background was superimposed.

    In my case, the code looks like this:

    <?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:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <com.google.android.material.bottomappbar.BottomAppBar
            android:id="@+id/bottom_app_bar"
            style="@style/Widget.MaterialComponents.BottomAppBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            app:backgroundTint="@color/colorGray"
            app:fabAlignmentMode="center" />
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom">
    
            <com.google.android.material.bottomnavigation.BottomNavigationView
                android:id="@+id/nav_view"
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_gravity="bottom"
                android:background="#80FFFFFF"
                android:icon="@drawable/bottom_nav_ic_assignment"
                app:itemIconTint="@color/bottom_nav_item_color"
                app:itemTextColor="@color/bottom_nav_item_color"
                app:labelVisibilityMode="selected"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:menu="@menu/bottom_nav_menu" />
    
        </FrameLayout>
    
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/addFab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:focusable="true"
            android:onClick="onFabClicked"
            android:src="@drawable/ic_add_white"
            app:backgroundTint="@color/colorBlue"
            app:fabSize="auto"
            app:layout_anchor="@+id/bottom_app_bar"
            app:layout_anchorGravity="center|top" />
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
    0 讨论(0)
  • 2020-11-30 01:21

    I found a quicker solution. I wrapped bottomnavigationview in frameLayout and everything work as expected. Try this:

        <?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/lt_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:fitsSystemWindows="false">
    
    
        <ViewPager
            android:id="@+id/main_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/bottom_navigation"
            android:layout_alignParentStart="true"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    
        <com.google.android.material.bottomappbar.BottomAppBar
            android:id="@+id/bottom_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:clickable="false"
            app:fabAlignmentMode="center" />
    
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom">
    
            <com.google.android.material.bottomnavigation.BottomNavigationView
                android:id="@+id/bottom_navigation"
                style="@style/BottomNavigationStyle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:clickable="false"
                app:menu="@menu/bottom_menu" />
    
    
        </FrameLayout>
    
    
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_anchor="@id/bottom_bar" />
    
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    
    0 讨论(0)
  • 2020-11-30 01:25

    First Way

    Try this You can Create a CustomBottomNavigationView

    Here is the good article for CustomBottomNavigationView

    How I draw custom shapes in BottomNavigationView

    SAMPLE CODE

    import android.content.Context;
    import android.graphics.*;
    import android.support.design.widget.BottomNavigationView;
    import android.support.v4.content.ContextCompat;
    import android.util.AttributeSet;
    
    public class CustomBottomNavigationView extends BottomNavigationView {
    
        private Path mPath;
        private Paint mPaint;
    
        /** the CURVE_CIRCLE_RADIUS represent the radius of the fab button */
        private final int CURVE_CIRCLE_RADIUS = 128 / 2;
        // the coordinates of the first curve
        private Point mFirstCurveStartPoint = new Point();
        private Point mFirstCurveEndPoint = new Point();
        private Point mFirstCurveControlPoint1 = new Point();
        private Point mFirstCurveControlPoint2 = new Point();
    
        //the coordinates of the second curve
        @SuppressWarnings("FieldCanBeLocal")
        private Point mSecondCurveStartPoint = new Point();
        private Point mSecondCurveEndPoint = new Point();
        private Point mSecondCurveControlPoint1 = new Point();
        private Point mSecondCurveControlPoint2 = new Point();
        private int mNavigationBarWidth;
        private int mNavigationBarHeight;
    
        public CustomBottomNavigationView(Context context) {
            super(context);
            init();
        }
    
        public CustomBottomNavigationView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public CustomBottomNavigationView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            mPath = new Path();
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mPaint.setColor(ContextCompat.getColor(getContext(),R.color.colorAccent));
            setBackgroundColor(Color.TRANSPARENT);
        }
    
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
    
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            // get width and height of navigation bar
            // Navigation bar bounds (width & height)
            mNavigationBarWidth = getWidth();
            mNavigationBarHeight = getHeight();
            // the coordinates (x,y) of the start point before curve
            mFirstCurveStartPoint.set((mNavigationBarWidth / 2) - (CURVE_CIRCLE_RADIUS * 2) - (CURVE_CIRCLE_RADIUS / 3), 0);
            // the coordinates (x,y) of the end point after curve
            mFirstCurveEndPoint.set(mNavigationBarWidth / 2, CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4));
            // same thing for the second curve
            mSecondCurveStartPoint = mFirstCurveEndPoint;
            mSecondCurveEndPoint.set((mNavigationBarWidth / 2) + (CURVE_CIRCLE_RADIUS * 2) + (CURVE_CIRCLE_RADIUS / 3), 0);
    
            // the coordinates (x,y)  of the 1st control point on a cubic curve
            mFirstCurveControlPoint1.set(mFirstCurveStartPoint.x + CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4), mFirstCurveStartPoint.y);
            // the coordinates (x,y)  of the 2nd control point on a cubic curve
            mFirstCurveControlPoint2.set(mFirstCurveEndPoint.x - (CURVE_CIRCLE_RADIUS * 2) + CURVE_CIRCLE_RADIUS, mFirstCurveEndPoint.y);
    
            mSecondCurveControlPoint1.set(mSecondCurveStartPoint.x + (CURVE_CIRCLE_RADIUS * 2) - CURVE_CIRCLE_RADIUS, mSecondCurveStartPoint.y);
            mSecondCurveControlPoint2.set(mSecondCurveEndPoint.x - (CURVE_CIRCLE_RADIUS + (CURVE_CIRCLE_RADIUS / 4)), mSecondCurveEndPoint.y);
    
            mPath.reset();
            mPath.moveTo(0, 0);
            mPath.lineTo(mFirstCurveStartPoint.x, mFirstCurveStartPoint.y);
    
            mPath.cubicTo(mFirstCurveControlPoint1.x, mFirstCurveControlPoint1.y,
                    mFirstCurveControlPoint2.x, mFirstCurveControlPoint2.y,
                    mFirstCurveEndPoint.x, mFirstCurveEndPoint.y);
    
            mPath.cubicTo(mSecondCurveControlPoint1.x, mSecondCurveControlPoint1.y,
                    mSecondCurveControlPoint2.x, mSecondCurveControlPoint2.y,
                    mSecondCurveEndPoint.x, mSecondCurveEndPoint.y);
    
            mPath.lineTo(mNavigationBarWidth, 0);
            mPath.lineTo(mNavigationBarWidth, mNavigationBarHeight);
            mPath.lineTo(0, mNavigationBarHeight);
            mPath.close();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawPath(mPath, mPaint);
        }
    }
    

    Now use like this

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/coordinatorlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerInParent="true"
            android:layout_marginBottom="30dp"
            android:clickable="true"
            android:focusable="true" />
    
        <neel.com.demo.CustomBottomNavigationView
            android:id="@+id/customBottomBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:background="@color/colorAccent"
            app:labelVisibilityMode="labeled" />
    
    
    </RelativeLayout>
    

    Activity

    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            CustomBottomNavigationView curvedBottomNavigationView = findViewById(R.id.customBottomBar);
            curvedBottomNavigationView.inflateMenu(R.menu.bottom_menu);
        }
    }
    

    OUTPUT

    Second Way

        <androidx.coordinatorlayout.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="120dp"
        android:layout_gravity="bottom">
    
        <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="58dp"
            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_favorite"
                    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_favorite"
                    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_favorite"
                    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_favorite"
                    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_favorite"
                    android:gravity="center"
                    android:orientation="vertical"
                    android:text="Personal"
                    android:textColor="#FFFFFF">
    
                </TextView>
    
            </LinearLayout>
    
        </com.google.android.material.bottomappbar.BottomAppBar>
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    OUTPUT

    0 讨论(0)
  • 2020-11-30 01:25

    There is an easier way to combine those 3 widgets. We could have something like:

    <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">
    
        <androidx.fragment.app.FragmentContainerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="?attr/actionBarSize" />
    
        <com.google.android.material.bottomappbar.BottomAppBar
            android:id="@+id/bottomBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            app:backgroundTint="?attr/colorPrimary"
            app:contentInsetEnd="0dp"
            app:contentInsetStart="0dp"
            app:fabAlignmentMode="end">
    
            <com.google.android.material.bottomnavigation.BottomNavigationView
                android:id="@+id/bottomNavigation"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:backgroundTint="@android:color/transparent"
                app:elevation="0dp"
                android:layout_marginEnd="100dp"
                app:itemIconTint="@android:color/white"
                app:itemRippleColor="@android:color/white"
                app:itemTextColor="@android:color/white"
                app:menu="@menu/menu_activity_home_bottom_navigation" />
    
        </com.google.android.material.bottomappbar.BottomAppBar>
    
        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:src="@drawable/ic_add_white_24dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_anchor="@id/bottomBar" />
    
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    And that's it.

    Depending on where the FAB is anchored (CENTER|END) the menu icons will be placed either to the left or in the middle:

    For this sample, the result would be something like:

    If you think there's a better way, please feel free to edit/comment so I can fix the post :)

    0 讨论(0)
  • 2020-11-30 01:27

    To all who use second approach from Nilesh Rathod comment and want remove unexpected space before first text view:

    Just set app:contentInsetStart="0dp" for BottomAppBar

    0 讨论(0)
提交回复
热议问题