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.
Related
I have a top bar and a bottom bar. I want to go to certain places from the top menu and to certain places from the bottom menu. But these two parts overlap each other, how can I solve this in the fragment. I make Twitter-style bottom and top components, but the fragment is overwritten.
I searched for fragment removal code but I couldn't find it.
Can you tell me where I went wrong?
Thanks.
FeedActivity2.kt
package com.ager.sutra
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.NavigationUI
import com.ager.sutra.databinding.ActivityFeed2Binding
import com.google.android.material.navigation.NavigationView
import com.ager.sutra.fragments.HomeFragment
import com.ager.sutra.fragments.MessageFragment
import com.ager.sutra.fragments.ProfileFragment
import com.ager.sutra.fragments.SearchFragment
class FeedActivity : AppCompatActivity() {
private lateinit var binding : ActivityFeed2Binding
private lateinit var fragmentLane : Fragment
private val homeFragment = HomeFragment()
private val searchFragment = SearchFragment()
private val messageFragment = MessageFragment()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityFeed2Binding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
val drawerLayout : DrawerLayout = findViewById(R.id.drawerLayout)
binding.imageMenu.setOnClickListener(View.OnClickListener {
drawerLayout.openDrawer(GravityCompat.START) })
val navView : NavigationView = findViewById(R.id.navigationView)
val navController : NavController =
Navigation.findNavController(this,R.id.navHostFragment)
try {
NavigationUI.setupWithNavController(navView, navController)
}catch (e : Exception){
println(e.localizedMessage)
}
val bottomNav = binding.bottomNavigation
bottomNav.setOnItemSelectedListener {
when(it.itemId){
R.id.bottom_home -> makeCurrentFragment(homeFragment)
R.id.bottom_search -> makeCurrentFragment(searchFragment)
R.id.bottom_messages -> makeCurrentFragment(messageFragment)
}
true
}
}
private fun makeCurrentFragment(fragment: Fragment) =
supportFragmentManager.beginTransaction().apply{
replace(R.id.navHostFragment, fragment)
commit()
}
}
activity_feed2.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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:id="#+id/drawerLayout"
tools:context=".FeedActivity"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/layoutToolBar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="#color/darkGray"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="15dp"
android:paddingEnd="15dp"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="#+id/imageMenu"
android:layout_width="24dp"
android:layout_height="24dp"
android:contentDescription="#string/app_name"
android:src="#drawable/ic_baseline_menu_24"
app:tint="#color/white" />
<TextView
android:id="#+id/textTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:text="#string/app_name"
android:textColor="#color/yellow"
android:textSize="20sp"
android:textStyle="bold"/>
</LinearLayout>
<fragment
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#id/layoutToolBar"
app:layout_constraintBottom_toTopOf="#id/bottom_navigation"
android:id="#+id/navHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost = "true"
app:navGraph="#navigation/main"
app:background="#color/darkGray"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/darkGray"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:itemRippleColor="#android:color/transparent"
app:itemIconSize="24dp"
app:labelVisibilityMode="unlabeled"
app:itemIconTint="#drawable/bottom_itemselector"
app:menu="#menu/bottom_menu"
>
</com.google.android.material.bottomnavigation.BottomNavigationView>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:menu="#menu/nav_menu"
app:headerLayout="#layout/nav_header"
android:layout_gravity="start"/>
</androidx.drawerlayout.widget.DrawerLayout>
main.xml (Navigation)
<?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/main"
app:startDestination="#+id/nav_home">
<fragment
android:id="#+id/nav_home"
android:name="com.ager.sutra.fragments.HomeFragment"
android:label="Home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/nav_profile"
android:name="com.ager.sutra.fragments.ProfileFragment"
android:label="Profile"
tools:layout="#layout/fragment_profile" />
<fragment
android:id="#+id/nav_settings"
android:name="com.ager.sutra.fragments.SettingsFragment"
android:label="Settings"
tools:layout="#layout/fragment_settings" />
<fragment
android:id="#+id/messageFragment"
android:name="com.ager.sutra.fragments.MessageFragment"
android:label="Message"
tools:layout="#layout/fragment_message" />
</navigation>
You will need to setup all over NavigationController.
Magic happens down below =)
setSupportActionBar(binding.appBarMain.toolbar);
DrawerLayout drawer = binding.drawerLayout;
NavigationView navigationView = binding.navView;
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setOpenableLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
Also, don't forget about OnSupportNavigateUp to handle drawer layout icon clicks
#Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
I'm trying to build in a hamburger menu into my Android (Kotlin) application. I thought I followed all of the steps, but only the back arrow show, which does nothing. I can however slide the menu from the left.
I then started a new application and tried to start from scratch, with the same result. Again the statusbar is shown, with only the back arrow.
I'm can't seem to find what I'm doing wrong.
Here's my code
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<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/nav_graph" />
</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"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
mainActivity.kt
package com.wensline.myapplication
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.navigation.NavigationView
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), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
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/Theme.AppCompat.Light.DarkActionBar">
<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" />
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Change this line of code
setupActionBarWithNavController(navController, appBarConfiguration)
To this
toolbar.setupWithNavController(navController, appBarConfiguration)
You need to set ActionBarDrawerToggle to achieve this -
private lateinit var drawerToggle: ActionBarDrawerToggle
In onCreate method you need to initialize drawerToggle as below -
drawerToggle = ActionBarDrawerToggle(this, drawer, toolbar,
R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawer.addDrawerListener(toggle)
toggle.setDrawerIndicatorEnabled(true)
toggle.syncState()
Thanks you for the suggestions. The answer of #KakyireLastBorn give me an idea. I changed the line
setupActionBarWithNavController(navController, appBarConfiguration)
to
toolbar.setupWithNavController(navController, drawerLayout)
This solved the issue !
I'm developing an Android app from "Navigation Drawer Activity" Template.
When I click on the Options menu, it shows an empty menu when it should show the Settings item.
I guess it could be because of the text color but I checked and for me it is not that.
Where is my error?
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
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>
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/Theme.BodetTag.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/bodet_icon_mini" />
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="?actionBarSize"
android:padding="#dimen/appbar_padding"
android:text="#string/app_name"
android:textAppearance="#style/TextAppearance.Widget.AppCompat.Toolbar.Title" />
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:tabSelectedTextColor="#color/white"
app:tabIndicatorColor="#color/white"
android:minHeight="?attr/actionBarSize" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
<androidx.viewpager.widget.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_settings"
android:orderInCategory="100"
android:title="#string/action_settings"
app:showAsAction="never" />
</menu>
MainActivity.kt:
package com.example.bodettag
import android.os.Bundle
import android.view.Menu
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.navigation.NavigationView
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 androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.viewpager.widget.ViewPager
import com.example.bodettag.ui.page.SectionsPagerAdapter
import com.google.android.material.tabs.TabLayout
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), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
val viewPager: ViewPager = findViewById(R.id.view_pager)
viewPager.adapter = sectionsPagerAdapter
val tabs: TabLayout = findViewById(R.id.tabs)
tabs.setupWithViewPager(viewPager)
}
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()
}
}
Please let me know if you see any possible improvements to my code, whether they are related to my problem or not.
Thanks for your help!
EDIT: What I want vs what I get
Make adjustments to your menu XML file.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_settings"
android:title="#string/action_settings"
app:showAsAction="ifRoom" /> // this is the key
</menu>
Add this into your app's theme
<item name="android:actionMenuTextColor">#color/black</item>
Currently, I am using the Navigation component from Android and the actionbar title is displayed on the left. However, I kind of want it centralised to make things neater, is there any way to go about doing so?
Image of the actionbar title that is displayed on the left
Activity's code:
public class General extends AppCompatActivity {
private BottomNavigationView bottomNavigationView;
private NavController navController;
private AppBarConfiguration appBarConfiguration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.general);
bottomNavigationView = findViewById(R.id.bottomNavigationView);
navController = Navigation.findNavController(this, R.id.fragment);
appBarConfiguration = new AppBarConfiguration.Builder(R.id.addFragment, R.id.homeFragment).build();
NavigationUI.setupWithNavController(bottomNavigationView, navController);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
}
}
Activity's XML Code
<?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=".General">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
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_navigation_menu">
</com.google.android.material.bottomnavigation.BottomNavigationView>
<fragment
android:id="#+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/the_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
Fragment XML Code:
<?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/the_navigation"
app:startDestination="#id/homeFragment">
<fragment
android:id="#+id/homeFragment"
android:name="com.test.HomeFragment"
android:label="Home"
tools:layout="#layout/home_fragment" />
<fragment
android:id="#+id/addFragment"
android:name="com.test.AddFragment"
android:label="Add"
tools:layout="#layout/add_fragment" />
</navigation>
After a bit of searching, it seems like this did the trick. All I had to do was to add it to my Activity code.
As the fragments are a childs of Parent activity, so we can centralize or customize the title as we want on the Parent Activity.
Here is an example how to center the title without doing the iterate for all View widgets ...
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navView = findViewById(R.id.nav_view)
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.
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_home, R.id.navigation_settings, R.id.navigation_info
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
// Detect on where fragment we are, and custom the title from here
navController
.addOnDestinationChangedListener { nc: NavController, nd: NavDestination, args: Bundle? ->
when(nd.id){
R.id.navigation_home -> {
supportActionBar?.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
supportActionBar?.setCustomView(R.layout.title_home_action_bar_layout)
}
R.id.navigation_settings -> {
supportActionBar?.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
supportActionBar?.setCustomView(R.layout.title_settings_action_bar_layout)
}
R.id.navigation_info -> {
supportActionBar?.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
supportActionBar?.setCustomView(R.layout.title_info_action_bar_layout)
}
}
}
}
For the custom centered title : title_settings_action_bar_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<TextView
android:id="#+id/tvTitle"
style="#style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Settings Baby Watcher"
android:textColor="#FFFFFF" />
</LinearLayout>
I cant set onclicklistener for navigationview in this code the menu is working but the menu items in navigation view is not working i have tried in options item selected and navigationitemselected listener too but its not working i have set the id in menu item and id in nav graph same but its not working
package com.nads.epicureapp
import android.content.Context
import android.content.res.Configuration
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.widget.Toolbar
import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.*
import androidx.navigation.ui.NavigationUI.onNavDestinationSelected
import androidx.navigation.ui.NavigationUI.setupWithNavController
import com.google.android.material.navigation.NavigationView
import com.nads.epicureapp.databinding.ActivityMainBinding
import dagger.hilt.android.AndroidEntryPoint
import androidx.navigation.ui.navigateUp
import com.google.android.material.bottomnavigation.BottomNavigationView
#AndroidEntryPoint
class MainActivity : AppCompatActivity(),NavigationView.OnNavigationItemSelectedListener{
private lateinit var appBarConfiguration : AppBarConfiguration
private lateinit var navController:NavController
private lateinit var binding: ActivityMainBinding
private lateinit var toolbar:Toolbar
private lateinit var navHostFragment: NavHostFragment
private lateinit var drawerLayout:DrawerLayout
private lateinit var navView:NavigationView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
toolbar = binding.root!!.findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragmentactivatedformain) as NavHostFragment
navController = navHostFragment.navController
drawerLayout = binding.root!!.findViewById(R.id.drawer_layout)
navView = binding.root!!.findViewById<NavigationView>(R.id.nav_view)
appBarConfiguration = AppBarConfiguration(setOf(R.id.homeFragment,R.id.profilePage,R.id.settings_dest),drawerLayout)
navView.setupWithNavController(navController)
navView.setNavigationItemSelectedListener(this)
NavigationUI.setupActionBarWithNavController(this,navController,appBarConfiguration)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.navigation, menu)
return true
}
override fun onSupportNavigateUp(): Boolean {
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragmentactivatedformain) as NavHostFragment
val navController = navHostFragment.navController
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.profilePage-> {
Log.e("NAV","nav selected working")
binding.root.findNavController().navigate(R.id.profilePage)
return true
}
else->
{
return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
}
}
// return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
Log.e("NAV","nav selected working2")
return true
}
}
This is the layout file for my activity main page
<?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_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start"
tools:context="com.nads.epicureapp.MainActivity">
<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"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="#+id/linearLayout"
app:layout_constraintTop_toTopOf="parent"
app:headerLayout="#layout/nav_header_menu"
app:menu="#menu/nav_drawer_menu" />
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/AppTheme.PopupOverlay" />
<fragment
android:id="#+id/fragmentactivatedformain"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="16dp"
app:defaultNavHost="true"
app:navGraph="#navigation/userprimary_navigation" />
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
this is my menu items in for navigationview drawerlayout where the profile page id is same as the id of in my navigation graph
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="#+id/primary">
<item
android:id="#+id/profilePage"
android:icon="#drawable/profileicon"
android:title="#string/userprofile" />
</group>
<item
android:id="#+id/settings_dest"
android:icon="#drawable/ic_app_settings"
android:title="#string/settings" />
</menu>
this is my navgraph which i use to navigate to the profile page in this navigation graph
<?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/userprimary_navigation"
app:startDestination="#id/homeFragment">
<fragment
android:id="#+id/homeFragment"
android:name="com.nads.epicureapp.ui.homepage.HomeFragment"
android:label="Epicure App"
tools:layout="#layout/fragment_home" >
<action
android:id="#+id/action_homeFragment_to_searchFoods"
app:destination="#id/searchFoods" />
<action
android:id="#+id/action_homeFragment_to_searchCooks"
app:destination="#id/searchCooks" />
</fragment>
<fragment
android:id="#+id/cooksPage"
android:name="com.nads.epicureapp.ui.homepage.CooksPage"
android:label="Cooks Page"
tools:layout="#layout/fragment_cooks_page" />
<fragment
android:id="#+id/searchFoods"
android:name="com.nads.epicureapp.ui.homepage.SearchFoods"
android:label="Serch foods"
tools:layout="#layout/fragment_search_foods" >
<action
android:id="#+id/action_searchFoods_to_foodDetails"
app:destination="#id/foodDetails" />
</fragment>
<fragment
android:id="#+id/searchCooks"
android:name="com.nads.epicureapp.ui.homepage.SearchCooks"
android:label="Serch Cooks"
tools:layout="#layout/fragment_search_cooks" >
<action
android:id="#+id/action_searchCooks_to_cooksPage"
app:destination="#id/cooksPage" />
</fragment>
<fragment
android:id="#+id/addRecipes"
android:name="com.nads.epicureapp.ui.homepage.AddRecipes"
android:label="Add Recipes"
tools:layout="#layout/fragment_add_recipes" />
<fragment
android:id="#+id/settings_dest"
android:name="com.nads.epicureapp.ui.homepage.Settings"
android:label="Settings"
tools:layout="#layout/fragment_settings" />
<fragment
android:id="#+id/foodDetails"
android:name="com.nads.epicureapp.ui.homepage.FoodDetails"
android:label="fragment_food_details"
tools:layout="#layout/fragment_food_details" />
<fragment
android:id="#+id/profilePage"
android:name="com.nads.epicureapp.ui.homepage.ProfilePage"
android:label="fragment_profile_page"
tools:layout="#layout/fragment_profile_page" />
</navigation>
You need to add when in onNavigationItemSelected as below
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.youritemid-> {
Log.e("NAV","nav selected working")
return true
}
return true
}
Here I got the answer the problem is we should put our navigation view after the linear layout component inside the drawerlayout after all the content views at the end of the drawerLayout
<?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_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start"
tools:context="com.nads.epicureapp.MainActivity">
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/AppTheme.PopupOverlay" />
<fragment
android:id="#+id/fragmentactivatedformain"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="16dp"
app:defaultNavHost="true"
app:navGraph="#navigation/userprimary_navigation" />
</LinearLayout>
<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"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="#+id/linearLayout"
app:layout_constraintTop_toTopOf="parent"
app:headerLayout="#layout/nav_header_menu"
app:menu="#menu/nav_drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
</layout>