Navigation drawer not showing up. AM I understand it right? - android

I'm making slidable menu and hamburger icon/sliding not working. I'm also not sure if this working how i think: when we are setting FragmentContainerView like this
<androidx.fragment.app.FragmentContainerView
app:navGraph="#navigation/nav_graph"
We are refer to Fragment set in navigation manager, am I right?
Code:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, EggTimerFragment.newInstance())
.commitNow()
}
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_graph) as NavHostFragment
val navController = navHostFragment.navController
findViewById<NavigationView>(R.id.nav_view)
.setupWithNavController(navController)
val appBarConfiguration = AppBarConfiguration(navController.graph, binding.drawerLayout)
NavigationUI.setupActionBarWithNavController(this, navController, binding.drawerLayout)
NavigationUI.setupWithNavController(binding.navView, navController)
binding.navView.setNavigationItemSelectedListener {
when(it.itemId){
R.id.item1 -> Toast.makeText(applicationContext, "item1 clicked", Toast.LENGTH_SHORT).show()
}
true
}
super.onCreate(savedInstanceState)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(toggle.onOptionsItemSelected(item)){
return true
}
return onOptionsItemSelected(item)
}
XML main_activity file:
<?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">
<androidx.drawerlayout.widget.DrawerLayout
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".app.MainActivity">
<androidx.fragment.app.FragmentContainerView
app:navGraph="#navigation/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:id="#+id/myNavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
/>
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:headerLayout="#layout/nav_header"
app:menu="#menu/nav_header_menu"
android:layout_gravity="start"
android:fitsSystemWindows="true"/>
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
Maybe I should cut some code and move it to fragment? Android guide is too briefly and unclear for me.

Please make this following changes:
Add android:fitsSystemWindows="true" to <androidx.drawerlayout.widget.DrawerLayout>
In your MainActivity override onSupportNavigateUp() method
Initialize data Binding like this:
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
Also there is no need for this code. Please remove it. As all the navigation should be managed by navigation graph.
if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.container, EggTimerFragment.newInstance()) .commitNow() }
I understand the Android Guide is too brief but you can refer to this particular section: Add a navigation drawer

Related

How to enable navigation drawer only when we are in a certain fragment?

I want to set my navigation drawer menu on a Fragment. I don't want the navigation drawer to show up when I start my app. I want it to show up after I enter another page (i.e. not first page). But the problem is, onSupportNavigateUp can only be written on MainActivity, which is the first page.
This is my MainActivity.kt :
class MainActivity : AppCompatActivity() {
private lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
#Suppress("UNUSED_VARIABLE")
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
drawerLayout = binding.drawerLayout
val navController = this.findNavController(R.id.myNavHostFragment)
NavigationUI.setupActionBarWithNavController(this,navController, drawerLayout)
NavigationUI.setupWithNavController(binding.navView, navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return NavigationUI.navigateUp(navController, drawerLayout)
}
}
Here is my activity_main.xml
`
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="#+id/myNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph="#navigation/navigation"
app:defaultNavHost="true"
/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/nav_header"
app:menu="#menu/navdrawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
`
It takes fragment_title.xml display and use it for activity_main.xml display by using fragment tag and NavHostFragment.
I also have another fragment called fragment_home.xml and HomeFragment.kt class.
What I don't know is, how to not show the navigation drawer when I'm on title fragment and start showing the navigation drawer when I'm on home fragment?
Below code will set navView visibility gone in TitleFragment and set visible on the other destinations:
navController.addOnDestinationChangedListener { _, destination, _ ->
if (destination.id == R.id.titleFragment) {
navView.visibility = View.GONE
} else {
navView.visibility = View.VISIBLE
}
}

How to destroy fragment and never come back to him

I switch fragments by navigation. I decided to add welcome screen with fragment to my app. I made welcome fragment as home fragment, so app starts with welcome fragment. After the welcome, I need to automatically switch to another fragment and destroy the starting fragment so that it can no longer be returned.But when fragment switches,the welcome fragment is visible under the new fragment. I solved it by android:background="?android:windowBackground". Now the new fragment overlaps the welcome fragment, but the welcome fragment still remains under the new fragment, and when I press the back arrow on the device, the welcome fragment appears again.I also removed the toolbar from the welcome fragment, and when the fragment switches, I show the toolbar, but the toolbar from the welcome fragment is displayed on the new fragment.Help my please. How to destroy welcome fragment and never come back to him?
This is main Activity
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
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)
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_food_text_analysis, R.id.nav_recipe_analysis,R.id.welcome_fragment), 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()
}
}
This is MainActivity xml file
<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/drawer_layout"
android:fitsSystemWindows="true"
tools:context=".MainActivity"
tools:openDrawer="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/toolbar_background"/>
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph = "#navigation/mobile_navigation"
app:defaultNavHost="true"
/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_gravity="start"
app:headerLayout="#layout/layout_header_main"
app:menu="#menu/activiy_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
This is Welcome Fragment
private lateinit var topAnimation: Animation
private lateinit var bottomAnimation: Animation
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_welcome_screen, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as AppCompatActivity).supportActionBar?.hide()
topAnimation = AnimationUtils.loadAnimation(activity, R.anim.top_animation)
bottomAnimation = AnimationUtils.loadAnimation(activity, R.anim.bottom_animation)
image_diet_girl.animation = topAnimation
welcome_text.animation = bottomAnimation
Handler().postDelayed({
(activity as AppCompatActivity).supportFragmentManager
.beginTransaction()
.setCustomAnimations(
R.anim.enter_from_right,
R.anim.exit_to_right
)
.replace(R.id.nav_host_fragment, FoodAnalysisFragment())
.commit()
},6000)
}
}
Navigation 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"
android:id="#+id/mobile_navigation"
app:startDestination="#id/welcome_fragment">
<fragment
android:id="#+id/nav_food_text_analysis"
android:name="com.example.nutritionfacts.ui.foodTextAnalysis.FoodAnalysisFragment"
android:label="Food analysis"
tools:layout="#layout/fragment_food_text_analysis" />
<fragment
android:id="#+id/nav_recipe_analysis"
android:name="com.example.nutritionfacts.ui.recipeAnalysis.RecipeAnalysis"
android:label="Recipe analysis"
tools:layout="#layout/fragment_recipe_analysis" />
<fragment
android:id="#+id/welcome_fragment"
android:name="com.example.nutritionfacts.ui.welcomeScreen.WelcomeScreen"
android:label="welcome screen"
tools:layout="#layout/fragment_welcome_screen" />
</navigation>

Kotlin Android Navigation Drawer item onclick listener does not working

I know this already asked many times, but in my case, I still don't get it.
So I have a navigation drawer that set up in the MainActivity.kt (My app has many fragment that runs on this Activity).
MainActivity.kt
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
lateinit var drawerLayout: DrawerLayout
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
drawerLayout = binding.drawerLayout
//Get navigation controller of this App
val navController = this.findNavController(R.id.myNavHostFragment)
//Lock the Nav drawer
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
NavigationUI.setupWithNavController(binding.navView, navController)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.nav_logout -> {
Toast.makeText(this, "Publication", Toast.LENGTH_SHORT).show()
Log.i("MainActivity", "Sign out clicked!")
}
R.id.nav_messages -> {
Toast.makeText(this, "Publication", Toast.LENGTH_SHORT).show()
}
}
binding.drawerLayout.closeDrawer(GravityCompat.START)
return true
}
// Set up the back button on action bar
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return NavigationUI.navigateUp(navController, drawerLayout)
}
}
This is my Activity_main.xml
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">
<androidx.drawerlayout.widget.DrawerLayout
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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/myNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph = "#navigation/navigation"
app:defaultNavHost = "true"
/>
</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"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header"
app:menu="#menu/nav_drawer_menu"/>
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
This is the menu layout for the navigation drawer:
nav_drawer_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group>
<item
android:id="#+id/nav_profile"
android:icon="#drawable/ic_person"
android:title="Profile"/>
<item
android:id="#+id/nav_messages"
android:icon="#drawable/ic_people"
android:title="Messages"/>
</group>
<item android:title="Account Settings">
<menu>
<item
android:id="#+id/nav_logout"
android:title="Sign Out"/>
</menu>
</item>
</menu>
This is how the navigation drawer looks like.
Am I missing something ? If there's anything unclear let me know.
You should use setNavigationItemSelectedListener.
Set a listener that will be notified when a menu item is selected.
navigationViewOBJ.setNavigationItemSelectedListener(this)
For DataBinding You should use
binding.navView.setNavigationItemSelectedListener(this)
I was facing the same issue and I changed my code in this manner to get Toast when Menuitems were select.
I removed NavigationView.OnNavigationItemSelectedListener this from
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener
created a variable in MainActivity class in MianActivity.kt
private lateinit var navView : NavigationView
assigned navView variable in override fun onCreate function like this by finding navigation view id like this
navView = findViewById(R.id.nav_menu)
which in your case is in activity_main.xml under this Section
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"
app:menu="#menu/nav_drawer_menu"/>
Then I implemented this function for onclick select
navView.setNavigationItemSelectedListener {}
I wrote switch case in this function same as your code and now it is working for me fine.

Android navigation onNavigationItemSelected not called

I have this DrawerLayout
<?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/stock_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/stock_app_bar"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_stock_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/stock_nav_header"
app:menu="#menu/stock_activity_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
and then in the activity I have the following onCreate function:
class StockMainActivity: AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_stock_main)
val toolbar: Toolbar = findViewById(R.id.stock_toolbar)
setSupportActionBar(toolbar)
val drawerLayout: DrawerLayout = findViewById(R.id.stock_drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_stock_view)
navView.bringToFront()
navView.setNavigationItemSelectedListener { item ->
if (item.itemId == R.id.nav_stock_home) {
finish()
}
true
}
val navController = findNavController(R.id.nav_stock_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_stock_home,
R.id.stock_navigation_fragment
), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_stock_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
But the navigation selected item listener is never called. It eventually navigates to the destination, but the listener is never called. I have checked similar posts, some suggesting to bring to the front the Navigation View, but to no avail. Please help ...
Ok, I have found the solution. I have put:
navView.bringToFront()
navView.setNavigationItemSelectedListener { item ->
if (item.itemId == R.id.nav_stock_home) {
finish()
}
true
}
At the end of onCreate... and it works now.

Android No view found for id when using toolbar button

when i click to toolbar button, galleryFragment should open thats what i want to do. But i got these error:
java.lang.IllegalArgumentException: No view found for id 0x7f080051 (com.example.myapplication:id/container) for fragment GalleryFragment{e255e88 (923e67b6-0b21-4fac-acf1-f85b79a3311a) id=0x7f080051}
My button id is: shop
you can see my codes in onOptionsItemSelected function.
do you have any ideas about it?
this is my MainActivity:
package com.example.myapplication
class MainActivity : AppCompatActivity() {
var manager = supportFragmentManager
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)
supportActionBar?.setDisplayShowTitleEnabled(false)
toolbar.setTitle("deneme")
val fab: FloatingActionButton = findViewById(R.id.fab)
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
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)
}
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 onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.shop -> {
var GalleryFragment = GalleryFragment()
var transaction = manager.beginTransaction()
transaction.add(R.id.container, GalleryFragment) //->
transaction.commit()
}
}
return super.onOptionsItemSelected(item)
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
This is my main xml(include my button):
<?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/shop"
android:title="shop"
android:icon="#drawable/shop"
app:showAsAction="always">
</item>
</menu>
this is my mainactivity.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" />
<include layout="#layout/toolbar">
</include>
<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>
create a framelayout or any other view and set id as
android:id="#+id/container" in your activity_main.xml layout file
then issue will be fixed.
Reason : R.id.container id is not found in your activity_main.xml file
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

Categories

Resources