Need the BottomNavigationView to always show by default (without any user interaction).
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppPopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment_content_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/drawer_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
Home fragment
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".presentation.ui.home.HomeFragment"
android:orientation="vertical">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewPagerContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:id="#+id/ad_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_anchorGravity="bottom"
android:background="#color/colorPrimary"
app:itemIconTint="#color/tab_selector"
app:itemTextColor="#color/tab_selector"
app:menu="#menu/bottom_navigation_menu"/>
</androidx.appcompat.widget.LinearLayoutCompat>
Unfortunately it seems that there is no answer yet on this anywhere. I tried to set layout_behavior, scrollFlags and layout_anchorGravity to bottom on BottomNavigationView but nothing works.
If I remove the scrollFlags on Toolbar only then the BottomNavigationView shows, but need the Toolbar having a scroll behavior but leaving the BottomNavigationView untouch.
The problem that the BottomNavigationView is affected by the scrolling flag set with app:layout_behavior in the activity container.
There is a couple of approaches you'd use to fix this:
First: add the BNV just below the CoordinatorLayout to be a part of the activity; so the layout would be:
<ConstraintLayout>
<CoordinatorLayout>
<AppBarLayout>
<content_main>
<frameLayout>
<BottomNavigationView>
Drawback: you could have other fragments transacted in the FragmentContainerView and the BNV won't be hidden in them. You can hide the BNV by setting its visibility.
Second: Transfer the ToolBar to the fragment; and set it when the fragment is created. The layout scheme would be:
Activity: just have the FragmentContainerView
Home Fragment
<ConstraintLayout>
<CoordinatorLayout>
<AppBarLayout>
<content_main>
<frameLayout>
<BottomNavigationView>
The drawback to this that you've to create and change the ToolBar for any fragment transaction in the FragmentContainerView.
Also you'd have a look at this similar question.
Related
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.MaterialToolbar
style="#style/Widget.MaterialComponents.Toolbar.Surface"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
app:title="#string/app_name" />
<androidx.fragment.app.FragmentContainerView
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:labelVisibilityMode="unlabeled"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
app:menu="#menu/menu_bottom_navigation" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
This attribute app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior" does not work inside LinearLayout, I tried to put BottomNavigationView outside LinearLayout, and the attribute above worked but I want to put FragmentContainerView above BottomNavigationView and at the same time make the attribute above work. How can I solve the problem?
Update your code like below:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/abl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<com.google.android.material.appbar.MaterialToolbar
style="#style/Widget.MaterialComponents.Toolbar.Surface"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
app:title="#string/app_name" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:labelVisibilityMode="unlabeled"
app:layout_behavior="#string/hide_bottom_view_on_scroll_behavior"
app:menu="#menu/menu_bottom_navigation" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I found a simple trick to solve the problem. Inside FragmentContainerView I'm showing a specific fragment and there is NestedScrollView inside the fragment.
I gave these attributes to the NestedScrollView
android:clipToPadding="false"
android:paddingBottom="Should be the same height of BottomNavigationView"
Now the content inside FragmentContainerView will be top of BottomNavigationView and never will touch BottomNavigationView.
The disadvantages of this way
It will leave extra space in the bottom but mostly
BottomNavigationView will cover it
If you give background color for NestedScrollView, The color will
touch BottomNavigationView
But at least it is working as I want.
I have top level container with CoordinatorLayout and Toolbar that hides when scolling, this container contain fragments.
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.screens.main.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
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:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
One of my fragments contain RecycleView and BottomNavigation
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:pp="http://schemas.android.com/tools"
android:id="#+id/cl_content"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.recyclerview.widget.RecyclerView/>
</androidx.core.widget.NestedScrollView>
<BottomNavigation />
</androidx.constraintlayout.widget.ConstraintLayout>
The problem that the BottomNavigation scrolls with the content, when the app start the BottomNavigation almost invisible, and when I scroll down the BottomNavigation became visible and vise versa, I need it to be static without scroll behavior, is there any configuration for that?
I guess the problem because BottomNavigation is not direct child of CoordinatorLayout but is there workaround?
Demo project(ignore slideshow and gallery):
https://github.com/pavelpoley/CoordinatorLayoutQuestion
Remove app:layout_behavior="#string/appbar_scrolling_view_behavior" from your content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:showIn="#layout/app_bar_main">
</androidx.constraintlayout.widget.ConstraintLayout>
UPDATE: After demo project has been updated with a more complex hierarchy provided solution above didn't work as expected.
I did a lot of research and couldn't find any clean solution to have BottomNavigationView inside CoordinatorLayout but not as a direct child.
The only solution was to move BottomNavigationView inside CoordinatorLayout as a child and then change its visibility based on androidx.navigation.NavController destination.
Source code: https://github.com/dautovicharis/CoordinatorLayoutQuestion/commits/master
You can make a couple of changes
Add exitUntilCollapsed flag to the Toolbar
app:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed"
Remove the app:layout_behavior from the NestedScrollView, and add it to root ConstraintLayout
By applying those, the layouts will be:
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.screens.main.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
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:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And fragment:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:pp="http://schemas.android.com/tools"
android:id="#+id/cl_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.recyclerview.widget.RecyclerView/>
</androidx.core.widget.NestedScrollView>
<BottomNavigation />
</androidx.constraintlayout.widget.ConstraintLayout>
So far I've managed to implement AppBarLayout and Toolbar with scroll flags and AppBar scrolling behavior and it all works great. My final goal is to implement something like this:
Netflix App Example
As you can see AppBar is transparent and the content is behind it. And everything else works perfectly.
From my observations when I put app:layout_behavior="#string/appbar_scrolling_view_behavior" (In my case I used app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior") tag CoordinatorLayout does not let me overlap Views (In this case AppBar should overlap my content).
This is my XML:
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/drawerLayout"
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"
android:fitsSystemWindows="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<fragment
android:id="#+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph="#navigation/root_nav_graph"
app:defaultNavHost="true"
/>
</FrameLayout>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior"
>
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/toolBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways|snap"
/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
The fragment holds layout with NestedScrollView as a Root.
Remove the attribute
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
from the Frame Layout. Also, set the attribute android:background="#android:color/transparent" to your toolbar.
I am building an app with a BottomNavigationView where the first tab is loaded correctly:
Tab 1:
However, when I switch to the next tab, it seems the Framelayout goes under the Toolbar like this:
Tab 2:
Tab 1 again:
This is my Layout:
<?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:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottom_navigation"/>
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:menu="#menu/bottom_nav_menu"
app:labelVisibilityMode="unlabeled"
app:itemBackground="#color/colorPrimary"
app:itemIconTint="#color/bottom_nav_color"
app:itemTextColor="#color/bottom_nav_color" />
</RelativeLayout>
There are similar cases like this one:
Part of Fragment items hides under Action bar
But their solutions don't work in my case. Any idea what should I change? Or why the Toolbar loses priority? I already tested to create one by myself in the Layout and it didn't work properly too.
P.S.
I'm loading some WebViews, but I doubt it influences.
Your code is working fine for me. Although you can set margin top for frame layout
android:layout_marginTop="?attr/actionBarSize"
I found how to fix it using a CoordinatorLayout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_above="#+id/bottom_navigation">
<FrameLayout
android:id="#+id/content_frame"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:menu="#menu/bottom_nav_menu"
app:labelVisibilityMode="unlabeled"
app:itemBackground="#color/colorPrimary"
app:itemIconTint="#color/bottom_nav_color"
app:itemTextColor="#color/bottom_nav_color" />
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
I got an idea from here:
https://forums.xamarin.com/discussion/146285/how-to-do-appbarlayout-with-collapsing-toolbarlayout-that-will-collapse-when-viewpager-scroll
Im using MaterialDrawer with a MainDrawerActivity where I replace each fragment inside container FrameLayout based on selected item, but I want to add a FAB (just for this fragment) that interacts with CoordinatorLayout so it can handle cool animations.
MainDrawer layout:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:minHeight="?actionBarSize"
android:theme="#style/Toolbar"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
How I replace each fragment:
try {
supportFragmentManager.beginTransaction().replace(R.id.container, FeedFragment()).commit()
} catch (e: IllegalStateException) {
Timber.i(e, "Fragment is still there.")
}
Fragment Layout:
<FrameLayout 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">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:listitem="#layout/feed_item" />
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="#dimen/spacing_medium"
android:layout_marginRight="#dimen/spacing_medium"
android:elevation="#dimen/elevation_little"
app:fabSize="normal"
app:layout_anchor="#+id/container"
app:layout_anchorGravity="bottom|right"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:srcCompat="#drawable/ic_add_white_18dp" />
</FrameLayout>
But as result the FAB button is behind bottom bar:
Im trying setting the coordinator layout attribues (layout_anchor and those) to match the main layout ids but it is not working...
why?
Define the Floating Action Button within the Activity - currently the Fragment's container is considered the parent.
FAB should be a direct child of CoordinatorLayout