When I try to open the NavigationView, it closes instantly so as it's not even shown at all. When I double click to open it, it shows for a brief second before closing again.
My MainActivity class:
class MainActivity : AppCompatActivity() {private lateinit var drawerLayout: DrawerLayoutprivate lateinit var navigationView: NavigationView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: androidx.appcompat.widget.Toolbar = findViewById(R.id.toolbar)
drawerLayout = findViewById(R.id.drawerLayout)
navigationView = findViewById(R.id.navigationView)
setSupportActionBar(toolbar)
val toggle = ActionBarDrawerToggle(
this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
setupNavigation()
}
private fun setupNavigation() {
navigationView.setNavigationItemSelectedListener {
when (it.itemId) {
R.id.quickAlarm -> showQuickAlarmFragment()
R.id.alarmList -> showAlarmListFragment()
R.id.info -> showInfoFragment()
}
true
}
}
private fun showQuickAlarmFragment() {
supportFragmentManager.beginTransaction()
.replace(R.id.container, QuickAlarmFragment.newInstance())
.commit()
}
private fun showAlarmListFragment() {
supportFragmentManager.beginTransaction()
.replace(R.id.container, AlarmListFragment.newInstance())
.commit()
}
private fun showInfoFragment() {
supportFragmentManager.beginTransaction()
.replace(R.id.container, InfoFragment.newInstance())
.commit()
}
}
My activity_main.xml:
<androidx.drawerlayout.widget.DrawerLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"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">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:elevation="4dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/navigation_header"
app:menu="#menu/navigation_menu"/>
</androidx.drawerlayout.widget.DrawerLayout>
I tried to implement a regular NavigationView but it closes instantly before it's shown.
Related
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
}
}
I build a graph programmatically using the Kotlin DSL.
fun NavGraphBuilder.addGraph(resources: Resources) {
navigation(
startDestination = NavigationGraphRoute.LoginFragment.buildFullPath(),
route = NavigationGraphRoute.NavGraph.buildFullPath()
) {
addDestinations(resources)
}
}
private fun NavGraphBuilder.addDestinations(resources: Resources) {
fragment<SignInFragment>(
route = NavigationGraphRoute.LoginFragment.buildFullPath()
) {
label = resources.getString(R.string.login_fragment_label)
}
fragment<HomeFragment>(
route = NavigationGraphRoute.HomeFragment.buildFullPath()
) {
label = resources.getString(R.string.home_label)
}
And in MainActiivty.kt
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setSupportActionBar(binding.toolbarMain)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
supportActionBar?.title = ""
val toggle =
ActionBarDrawerToggle(
this,
binding.drawerLayout,
binding.toolbarMain,
R.string.open,
R.string.close
)
binding.drawerLayout.addDrawerListener(toggle)
toggle.syncState()
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
navController.createGraph(
startDestination = NavigationGraphRoute.LoginFragment.buildFullPath()
) {
addAuthGraph(resources = resources)
}
appBarConfiguration = AppBarConfiguration(navController.graph, binding.drawerLayout)
NavigationUI.setupWithNavController(binding.toolbarMain, navController, appBarConfiguration)
}
}
and in 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar_main"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/greys_white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.fragment.app.FragmentContainerView
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"
android:layout_marginTop="?attr/actionBarSize"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="#+id/toolbar_main"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Custom Navigation Drawer Start -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/navigation_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:orientation="vertical">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.drawerlayout.widget.DrawerLayout>
So the question is, how can I set the top-level destination for HomeFragment in AppBarConfiguration
Currently it setted like appBarConfiguration = AppBarConfiguration(navController.graph, binding.drawerLayout)
So, how can I set appBarConfiguration in such a way where I can set HomeFragment as TopLevelDestination. The reason why i needed as top is on the HomeFragment I need to see the Hamburger menu in toolbar and on another fragment it should show back. As I using Single Activity Architecture.
this is MainActivity
class MainActivity : AppCompatActivity(), FragmentDrawerListener,
BottomNavigationView.OnNavigationItemSelectedListener {
private lateinit var drawerFragment: DrawerFragment
#Inject
lateinit var mainActivityViewModel: MainActivityViewModel
#Inject
lateinit var appPreference: AppPreference
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidInjection.inject(this)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
navigation.setOnNavigationItemSelectedListener(this)
displayView()
}
override fun onBackPressed() {
if (drawer_layout.isDrawerOpen(GravityCompat.START)) {
drawer_layout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}
override fun onDrawerItemSelected(view: View, position: Int) {
displayView(position)
}
private fun displayView() {
drawerFragment =
supportFragmentManager.findFragmentById(R.id.fragment_navigation_drawer) as DrawerFragment
drawerFragment.init(R.id.fragment_navigation_drawer, drawer_layout, toolbar)
displayView(0)
}
private fun displayView(position: Int) {
when (position) {
0 -> {
HomeFragment()
}
5 -> {
val intent = Intent(this, MerchantOnBoardingActivity::class.java)
startActivity(intent)
}
9 -> {
val intent = Intent(this, AppSecurityActivity::class.java)
startActivity(intent)
}
else -> {
val bundle = Bundle()
bundle.putInt("menuItemPosition", position - 1)
val intent = Intent(this, MenuActivity::class.java)
intent.putExtras(bundle)
startActivity(intent)
}
}
}
private fun showDefaultPage() {
val fragment = HomeFragment()
title = "Home"
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.main_content, fragment)
fragmentTransaction.commit()
supportActionBar?.title = title
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
var fragment: Fragment? = null
when (item.itemId) {
R.id.navigation_home -> fragment = HomeFragment()
R.id.navigation_monitor -> Toast.makeText(this, "Monitor", Toast.LENGTH_LONG).show()
R.id.navigation_profile -> Toast.makeText(this, "Profile", Toast.LENGTH_LONG).show()
}
return loadFragment(fragment)
}
private fun loadFragment(fragment: Fragment?): Boolean {
//switching fragment
if (fragment != null) {
supportFragmentManager
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit()
return true
}
return false
}
}
This is my xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:local="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<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="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
local:popupTheme="#style/ThemeOverlay.AppCompat.Light"
local:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<FrameLayout
android:id="#+id/main_content"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemIconTint="#color/design_default_color_primary"
app:itemTextColor="#color/design_default_color_primary"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
</LinearLayout>
<fragment
android:id="#+id/fragment_navigation_drawer"
android:name="com.egpaid.employeeapp.home.homedashboard.DrawerFragment"
android:layout_width="260dp"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout="#layout/fragment_drawer"
tools:layout="#layout/fragment_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
</LinearLayout>
</RelativeLayout>
using this code i am able to display data but when i try to click on Home button on either from bottom navigation view or from drawber then i am getting
No view found for id 0x7f0900a3 (com.egpaid.employeeapp:id/fragment_container) for fragment HomeFragment{9d6bf5} (7b531975-d1d4-4ad4-b3c7-6f43ae436c6d) id=0x7f0900a3}
I don't know what i am missing i am trying to create custom navigation drawber with bottom navigation view please help me Thanks
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>
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.