I created a bottom navigation in main activity and does not show menu icon or text
I use the material library version 1.7.0
I changed the version to 1.6.1 and 1.5, but there was still a problem
I invalidate caches and the problem was not solved
I also used the clean project/rebuild project, but the problem was not solved
what is the problem?
activity_main.xml
<layout
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">
<data>
</data>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<RelativeLayout
android:id="#+id/mainActivityBase"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:gravity="center"
android:textAppearance="?textAppearanceHeadline4"
android:layout_marginTop="25dp"/>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="64dp"
android:clipToPadding="false"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_movie_player"
tools:layout="#layout/fragment_home" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationMain"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_alignParentBottom="true"
android:layout_marginStart="#dimen/marginStart"
android:layout_marginEnd="#dimen/marginEnd"
android:layout_marginBottom="#dimen/marginStart"
android:elevation="8dp"
app:labelVisibilityMode="unlabeled"
app:menu="#menu/movie_player_menu"
app:itemIconSize="28dp"
app:itemRippleColor="#android:color/transparent"
/>
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>
movie_player_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/homeFragment"
android:title="#string/home"
android:icon="#drawable/ic_round_home_24" />
<item android:id="#+id/searchFragment"
android:title="#string/search"
android:icon="#drawable/ic_round_search_24" />
<item android:id="#+id/profileFragment"
android:title="#string/profile"
android:icon="#drawable/ic_round_person_24" />
</menu>
Navigation components setup
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.lifecycleOwner = this
setupBottomNavigationBar()
}
private fun setupBottomNavigationBar() {
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNavigationMain)
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_container
) as NavHostFragment
navController = navHostFragment.navController
bottomNavigationView.setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration(
setOf(R.id.homeFragment, R.id.searchFragment, R.id.profileFragment)
)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration)
}
I run it on a physical phone but the problem was still there
Update
I found the problem set windowTranslucentNavigation false and problem is solved
Related
My version of nav is 2.4.2
My problem is that when the app goes to background the bottomNav doesn't work after re enter the app in some situations.
For example, I am in the third nav. I leave the app with the home button and if I open the app again all works correctly. But if I start to open a lot of apps and after entering my app the bottomNav doesn't work. It changes the symbol colors, but doesn't navigate. The backstacks of the current nav still work.
And here is my code to set the navigation.
MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
if(savedInstanceState == null){
setupBottomNavigationBar()
}
}
private fun setupBottomNavigationBar(){
val graphs = setOf(
R.id.firstFragment,
R.id.secondFragment,
R.id.thirdFragment,
R.id.fourthFragment,
R.id.fithFragment
)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_container) as NavHostFragment
currentNavController = navHostFragment.navController
val bottomNavigation = findViewById<BottomNavigationView>(R.id.bottom_navigation)
bottomNavigation.setupWithNavController(currentNavController)
appBarConfiguration = AppBarConfiguration(graphs)
}
activityMain.xml
<LinearLayout 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:orientation="vertical"
tools:context=".activities.MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="#navigation/super_nav"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="#menu/bottom_nav"
app:itemIconTint="#drawable/botton_navigation_colors"
app:labelVisibilityMode="unlabeled"
app:itemIconSize="35dp"
/>
bottom_nav.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/first_navigation"
android:icon="#drawable/ic_first_black"
android:contentDescription="#string/first_desc"
android:title="#string/first_title" />
<item
android:id="#+id/second_navigation"
android:icon="#drawable/ic_second"
android:contentDescription="#string/second_desc"
android:title="#string/second_title" />
<item
android:id="#+id/third_navigation"
android:icon="#drawable/ic_third"
android:contentDescription="#string/third_desc"
android:title="#string/third_title" />
<item
android:id="#+id/fourth_navigation"
android:icon="#drawable/ic_fourth"
android:contentDescription="#string/fourth_desc"
android:title="#string/fourth_title" />
<item
android:id="#+id/fifth_navigation"
android:icon="#drawable/ic_fifth"
android:contentDescription="#string/fifth_desc"
android:title="#string/fifth_title" />
super_nav.xml
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/super_nav"
app:startDestination="#+id/main_navigation">
<include app:graph="#navigation/first_navigation"/>
<include app:graph="#navigation/second_navigation"/>
<include app:graph="#navigation/third_navigation" />
<include app:graph="#navigation/fourth_cart_navigation" />
<include app:graph="#navigation/fifth_navigation" />
I'm trying to make an memo app, and this is my first time with application programming.
When I tried to run the code on my device it just dies after showing the IntroActivity and the error log says: "You must call setGraph() before calling getGraph()"
Below is the code.
class ListActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityListBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityListBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbar)
val navController = findNavController(R.id.nav_host_fragment_content_list)
appBarConfiguration = AppBarConfiguration(navController.graph)
setupActionBarWithNavController(navController, appBarConfiguration)
binding.fab.setOnClickListener { view ->
val intent=Intent(applicationContext, DetailActivity::class.java)
startActivity(intent)
}
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_list)
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
}
When I googled about this error there were only answers about androidx.navigation version 2.3.0-alpha2, so I checked my build.gradle.
I was using 2.5.0, the latest version.
How else can I solve this problem?
activity_list.xml
<?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=".ListActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Theme.DimoMemo.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/Theme.DimoMemo.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_list" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="#dimen/fab_margin"
android:layout_marginBottom="16dp"
app:srcCompat="#drawable/ic_add"
android:layout_marginRight="#dimen/fab_margin" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
content_list.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<fragment
android:id="#+id/nav_host_fragment_content_list"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp" />
</FrameLayout>
check if the layout contains:
app:navGraph="#navigation/nav_graph"
app:defaultNavHost="true"
your nav_host_fragment_content_list must look like:
<fragment
android:id="#+id/nav_host_fragment_content_list"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:navGraph="#navigation/your_nav_graph"
app:defaultNavHost="true" />
https://developer.android.com/guide/navigation/navigation-getting-started
I have an activity that has a fragment layout dedicated to the toolbar. In the center we have a normal nav_host container.
The activity contains one fragment that correctly shows the hamburger. If I click a button it gets replaced from a second fragment that replace the old toolbar with a new one. After clicking back the new toolbar is replaced by the old one.
The problem is that the hamburger icon doesn't show up and the toolbar doesn't work as expected. Ideas?
This is the code in the activity:
open fun setupToolbar() {
initialToolbar = ToolbarFragment()
setToolbarFragment(initialToolbar){
setNavController()
}
}
fun setToolbarFragment(fragment: Fragment, callback: () -> (Unit) = {}) {
supportFragmentManager
.beginTransaction()
.replace(R.id.toolbarContainer, fragment)
.runOnCommit {
callback.invoke()
}.commit()
}
private fun setNavController() {
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = setFragmentsWithHamburgerMenu(navController)
toolbar.setupWithNavController(navController, appBarConfiguration)
}
fun setFragmentsWithHamburgerMenu(navController: NavController): AppBarConfiguration {
return AppBarConfiguration(
setOf(
R.id.analyticsFragment,
R.id.routinesFragment,
R.id.currentRunFragment,
R.id.myMapsFragment,
R.id.myRobotsFragment
),
drawer_layout
)
}
This is the code instead of the second fragment:
override fun onResume() {
super.onResume()
val fragment = SearchToolbarFragment(searchHint, this::onQueryTextChange)
baseActivity.setToolbarFragment(fragment) {
// other stuff
}
}
override fun onPause() {
super.onPause()
baseActivity.setupToolbar()
}
This instead is my activity layout:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="viewModel" type="[package].DashboardViewModel" />
</data>
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/toolbarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"/>
<fragment
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottom_nav"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbarContainer" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav"
style="#style/BottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
app:itemBackground="#color/white"
app:itemTextColor="#color/button_view_item"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/menu_bottom_nav" />
<LinearLayout
android:id="#+id/progressMaskLayout"
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_toBottomOf="#+id/toolbarContainer">
<include layout="#layout/progress_mask" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true">
<include
bind:viewModel="#{viewModel}"
layout="#layout/element_navigation_bar"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
To avoid the problem I just added a fragment over the previous one and I removed the added one.
Like this:
fun addToolbarFragment(fragment: Fragment, callback: () -> (Unit) = {}) {
supportFragmentManager
.beginTransaction()
.add(R.id.toolbarContainer, fragment)
.runOnCommit {
callback.invoke()
}.commit()
}
fun removeToolbarFragment(fragment: Fragment, callback: () -> (Unit) = {}) {
supportFragmentManager
.beginTransaction()
.remove(fragment)
.runOnCommit {
callback.invoke()
}.commit()
}
In this way, all the customization done in the first toolbar won't be lost.
First, you're using Android jetpack navigation component but also using fragment manager to manually do fragment transactions. You're defying the purpose of using the jetpack navigation component. That's the whole point of using the navigation library so that we don't have to manually do the fragment transactions. What you have to do here is put your toolbar in the main_activity.xml so that all fragments can inherit it.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/Drawer_Main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/Layout_Coordinator_Main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/Toolbar_Main"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary">
<TextView
android:id="#+id/Toolbar_Main_Title"
style="#style/Locky.Text.Toolbar.TitleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/app_name" />
</com.google.android.material.appbar.MaterialToolbar>
<androidx.core.widget.NestedScrollView
android:id="#+id/Nested_Scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:fillViewport="true">
<fragment
android:id="#+id/Navigation_Host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/navigation_drawer_main" />
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/FAB_Add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
app:srcCompat="#drawable/ic_add" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/Navigation_View"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:clipToPadding="false"
android:paddingStart="0dp"
android:paddingEnd="16dp"
app:headerLayout="#layout/drawer_header"
app:menu="#menu/menu_drawer_main" />
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
I'm using SDK 28 and android X element.
I'm trying imitate Instagram's UI
I had already try to combine two deafult navigation from Android Studio template.
And it has some coulples bug that I can't fix.
I'm coding Navigation on MainActivity.kt
Take example like :
1.Missing the Humbuger Icon at Fragment what launch by Bottom Navigation
2.Drawer Navigation Didn't Cover Navigation
Code
Main Activity
package com.odstudio.ourdiet
import android.os.Bundle
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.navigation.NavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import com.google.android.material.bottomnavigation.BottomNavigationView
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.nav_gallery, R.id.nav_slideshow, R.id.nav_tools, R.id.nav_share, R.id.nav_send
), drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
val bottomNavView: BottomNavigationView = findViewById(R.id.navigation)
bottomNavView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
// override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
// menuInflater.inflate(R.menu.main, menu)
//return true
// }
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
private val mOnNavigationItemSelectedListener =
BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
findNavController(R.id.nav_host_fragment).navigate(R.id.nav_home)
}
R.id.navigation_groups -> {
findNavController(R.id.nav_host_fragment).navigate(R.id.nav_groups)
}
R.id.navigation_friends -> {
findNavController(R.id.nav_host_fragment).navigate(R.id.nav_friends)
}
}
false
}
}
Layout
Activity_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"
android:fitsSystemWindows="true">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:elevation="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/activity_main_bottom" />
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="-200dp"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
app_bar_main.xml
<?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=".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="match_parent"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay"/>
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
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">
<fragment
android:id="#+id/nav_host_fragment"
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/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
Image
Home Page WithoutHumbuger Icon
Drawer Navigation Didn't Cover Navigation
OK, this one was pretty straight forward. I took the default nav drawer project and added a few changes.
First, wrap the DrawerLayout and your added BottomNavigation in a ConstraintLayout.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true">
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:elevation="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
Then in MainActivy add the OnNavigationSelectedListener and set it in onCreate()
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
R.id.nav_tools, R.id.nav_share, R.id.nav_send
), drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
// Set up navigation here
when (item.itemId) {
R.id.navigation_rivers -> findNavController(R.id.nav_host_fragment).navigate(R.id.nav_river)
} R.id.navigation_favorites -> findNavController(R.id.nav_host_fragment).navigate(R.id.nav_favs)
R.id.navigation_map -> findNavController(R.id.nav_host_fragment).navigate(R.id.nav_map)
}
false
}
And make sure you have your bottom nav menu setup.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_rivers"
android:icon="#drawable/ic_sea"
android:title="#string/title_rivers"/>
<item
android:id="#+id/navigation_favorites"
android:icon="#drawable/ic_heart"
android:title="#string/title_favorites"/>
<item
android:id="#+id/navigation_map"
android:icon="#drawable/ic_location"
android:title="#string/title_map"/>
</menu>
UPDATE:
I updated MainActivity.kt above.
Here is my nav graph mobile_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/mobile_navigation"
app:startDestination="#+id/nav_home">
<!-- Other Drawer Fragments here, removed for brevity -->
<fragment
android:id="#+id/nav_share"
android:name="com.stackoverflowdualnav.ui.share.ShareFragment"
android:label="#string/menu_share"
tools:layout="#layout/fragment_share" />
<fragment
android:id="#+id/nav_send"
android:name="com.stackoverflowdualnav.ui.send.SendFragment"
android:label="#string/menu_send"
tools:layout="#layout/fragment_send" />
<!-- Bottom Nav Below -->
<fragment
android:id="#+id/nav_river"
android:name="com.stackoverflowdualnav.ui.send.RiverFragment"
android:label="#string/menu_river"
tools:layout="#layout/fragment_river" />
<fragment
android:id="#+id/nav_favs"
android:name="com.stackoverflowdualnav.ui.send.FavoritesFragment"
android:label="#string/menu_favorites"
tools:layout="#layout/fragment_map" />
<fragment
android:id="#+id/nav_map"
android:name="com.stackoverflowdualnav.ui.send.NavMapFragment"
android:label="#string/menu_map"
tools:layout="#layout/fragment_map" />
This works as-is, just adapt it to your use case.
I'm trying the jetpack navigation and can't show the navigation back button when I move to a new fragment.
NavigationActivity.kt
class NavActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_navigation)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
val host: NavHostFragment = supportFragmentManager
.findFragmentById(R.id.navigation_graph) as NavHostFragment? ?: return
// Set up Navigation
val navController = host.navController
setupActionBarWithNavController(navController)
setupBottomNavMenu(navController)
}
private fun setupActionBarWithNavController(navController: NavController) {
setupActionBarWithNavController(this, navController)
}
private fun setupBottomNavMenu(navController: NavController) {
findViewById<BottomNavigationView>(R.id.bottom_nav_view)?.let { bottomNavView ->
NavigationUI.setupWithNavController(bottomNavView, navController)
}
}
}
activity_navigation.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"
tools:context=".views.NavActivity">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:background="?attr/colorPrimary"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:layout_width="match_parent">
</androidx.appcompat.widget.Toolbar>
<fragment
android:id="#+id/navigation_graph"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbar"
app:navGraph="#navigation/navigation_graph"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="#menu/menu_bottom_nav" />
navigation_graph.xml
<navigation 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:startDestination="#+id/launcher_home">
<fragment
android:id="#+id/launcher_home"
android:name="com.noisyninja.androidlistpoc.views.main.MainFragment"
android:label="#string/app_name"
tools:layout="#layout/fragment_main">
<action
android:id="#+id/next_action"
app:destination="#+id/detailFragment"
app:enterAnim="#anim/slide_in_right"
app:exitAnim="#anim/slide_out_left"
app:popEnterAnim="#anim/slide_in_left"
app:popExitAnim="#anim/slide_out_right" />
</fragment>
<fragment
android:id="#+id/detailFragment"
android:name="com.noisyninja.androidlistpoc.views.detail.DetailFragment"
android:label="DetailFragment" />
</navigation>
code for navigation:
/**
* opens detail activity
*/
override fun showDetail(view: View, me: Me) {
var bundle = Bundle()
bundle.putString("key", "value")
Navigation.findNavController(view).navigate(R.id.next_action, bundle, null)
}
As above when navigation to the second fragment the toolbar goes missing entirely and doesn't show the back button.
Hitting the hardware back button also doesn't pop the detail view.
The first hit has no effect, the second hit quits the app.
Override this method in your Activity with nav_host_fragment
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
Edit: Your DetailFragment contains the line
DataBindingUtil.setContentView<FragmentDetailBinding>(requireActivity(),
R.layout.fragment_detail)
which is resetting the content of your Activity to only be your fragment_detail layout, wiping out the NavHostFragment and everything else.
You should be using DataBindingUtil.bind<FragmentDetailBinding>(view)!! instead.
Original answer (you should still do this, but the above answer is actually what solves the problem)
Your ConstraintLayout is missing quite a few constraints (your views should be a vertical chain, where every app:layout_constraintTop_toBottomOf has an alternative app:layout_constraintBottom_toTopOf on the other element, etc.).
Since you have a single set of three vertically aligned items, you don't need a ConstraintLayout - just a LinearLayout is enough:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="vertical"
tools:context=".views.NavActivity">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:background="?attr/colorPrimary"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:layout_width="match_parent"/>
<fragment
android:id="#+id/navigation_graph"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="#navigation/navigation_graph"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="#menu/menu_bottom_nav" />
</LinearLayout>