I have created my navigation and menu files in the res directory for a bottom navigation view using navigation UI.
I have also set my navigation host fragment within the activity main xml file and the nav controller for my bottom navigation view within the main activity class.
There are three navigation graphs and one main navigation file including the three graphs with the include tag which is referenced in the navigation host fragment in the nav graph property.
I tried switching the background color for each one of the fragments to check if the bottom navigation view is working but all fragments remain white.
Here is my code
Navigation files
First 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/nav_graph_home"
app:startDestination="#id/home_dest">
<fragment
android:id="#+id/home_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.HomeFragment"
android:label="RecommendedTrips"
tools:layout="#layout/fragment_home">
<action
android:id="#+id/action_home_to_activities_and_points_of_interest"
app:destination="#+id/activities_and_points_of_interest_dest"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_exit_anim"
app:popExitAnim="#anim/nav_default_enter_anim"
/>
<action
android:id="#+id/action_home_to_cities"
app:destination="#+id/cities_dest"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_exit_anim"
app:popExitAnim="#anim/nav_default_enter_anim"
/>
</fragment>
<fragment
android:id="#+id/activities_and_points_of_interest_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.ActivitiesAndPointsOfInterestFragment"
android:label="Activities and points of interest"
tools:layout="#layout/fragment_activities_and_points_of_interest"
>
<action
android:id="#+id/action_activities_and_points_of_interest_to_activities_detail"
app:destination="#+id/activity_detail_dest"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_exit_anim"
app:popExitAnim="#anim/nav_default_enter_anim"
/>
<action
android:id="#+id/action_activities_and_points_of_interest_to_point_of_interest_detail"
app:destination="#+id/point_of_interest_detail_dest"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_exit_anim"
app:popExitAnim="#anim/nav_default_enter_anim"
/>
</fragment>
<fragment
android:id="#+id/cities_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.CitiesFragment"
android:label="Cities"
tools:layout="#layout/fragment_cities"
>
<action
android:id="#+id/cities_to_action_activities_and_points_of_interest"
app:destination="#+id/activities_and_points_of_interest_dest"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_exit_anim"
app:popExitAnim="#anim/nav_default_enter_anim"
/>
</fragment>
<fragment
android:id="#+id/activity_detail_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.ActivityDetailFragment"
android:label="Activity"
tools:layout="#layout/fragment_activity_detail"
>
</fragment>
<fragment
android:id="#+id/point_of_interest_detail_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.PointOfInterestDetailFragment"
android:label="Point of interest"
tools:layout="#layout/fragment_local_point_of_interest_detail"
>
</fragment>
</navigation>
Second 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/nav_graph_my_trips"
app:startDestination="#id/my_trips_dest">
<fragment
android:id="#+id/my_trips_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.MyTripsFragment"
android:label="My trips"
tools:layout="#layout/fragment_my_trips"
>
<action
android:id="#+id/action_my_trips_to_local_activities_and_points_of_interest"
app:destination="#+id/local_activities_and_points_of_interest_dest"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_exit_anim"
app:popExitAnim="#anim/nav_default_enter_anim"
/>
</fragment>
<fragment
android:id="#+id/local_activities_and_points_of_interest_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.LocalActivitiesAndPointsOfInterestFragment"
android:label="My activities and points of interest"
tools:layout="#layout/fragment_local_activities_and_points_of_interest"
>
<action
android:id="#+id/local_activities_and_points_of_interest_to_local_activity_detail"
app:destination="#+id/local_activity_detail_dest"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_exit_anim"
app:popExitAnim="#anim/nav_default_enter_anim"
/>
<action
android:id="#+id/local_activities_and_points_of_interest_to_local_point_of_interest_detail"
app:destination="#+id/local_point_of_interest_detail_dest"
app:enterAnim="#anim/nav_default_enter_anim"
app:exitAnim="#anim/nav_default_exit_anim"
app:popEnterAnim="#anim/nav_default_exit_anim"
app:popExitAnim="#anim/nav_default_enter_anim"
/>
</fragment>
<fragment
android:id="#+id/local_activity_detail_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.LocalActivityDetailFragment"
android:label="Activity title"
tools:layout="#layout/fragment_local_activity_detail"
>
</fragment>
<fragment
android:id="#+id/local_point_of_interest_detail_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.LocalActivityDetailFragment"
android:label="Activity title"
tools:layout="#layout/fragment_local_activity_detail"
>
</fragment>
</navigation>
Third 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:tool="http://schemas.android.com/tools"
android:id="#+id/nav_graph_settings"
app:startDestination="#id/settings_dest">
<fragment
android:id="#+id/settings_dest"
android:name="io.keepcoding.mvvmarchitecture.ui.SettingsFragment"
android:label="Settings"
tool:layout="#layout/fragment_settings"
>
</fragment>
</navigation>
Menu file for bottom navigation view
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/nav_graph_home"
android:icon="#drawable/ic_home"
android:title="Main" />
<item
android:title="My trips"
android:id="#+id/nav_graph_my_trips"
android:icon="#drawable/ic_my_trips" />
<item
android:title="Settings"
android:id="#+id/nav_graph_settings"
android:icon="#drawable/ic_settings"
/>
</menu>
Main graph file with include tags
<?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"
android:id="#+id/nav_graph"
app:startDestination="#+id/nav_graph_home"
>
<include app:graph="#navigation/nav_graph_home"/>
<include app:graph="#navigation/nav_graph_my_trips"/>
<include app:graph="#navigation/nav_graph_settings"/>
</navigation>
Activity main xml file
<?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:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Theme.MVVMArchitecture.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.MVVMArchitecture.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/navHostContainer"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_marginTop="130dp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="#id/bottomNavigation"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="?android:attr/windowBackground"
app:menu="#menu/tab_bar_menu" />
</RelativeLayout>
Activity main kotlin file
package io.keepcoding.mvvmarchitecture.ui
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import io.keepcoding.mvvmarchitecture.R
import kotlinx.android.synthetic.main.activity_main.*
#Suppress("CAST_NEVER_SUCCEEDS")
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.navHostContainer) as NavHostFragment // We suppress cast never succeeds so the compiler does not complain
val navController = navHostFragment.navController
bottomNavigation.setupWithNavController(navController)
}
private fun loadFragment(fragment: Fragment){
supportFragmentManager.beginTransaction()
.replace(R.id.navHostContainer, fragment)
.commit()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
}
Related
I want to use the navigation and destination system in android so when a menu item in the bottom nav bar is clicked it goes to a fragment.
I created 3 empty fragments and followed this guide to tie the items to the fragments but when I click the menu items, nothing happens.
https://developer.android.com/guide/navigation/navigation-ui
I made sure that the item id from the menu has the same id as the fragment too.
how can I make this work?
Here is my Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navController = findNavController(R.id.nav_host_fragment)
bottom_navigation
.setupWithNavController(navController)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
}
}
This is the activity 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"
android:id="#+id/coordinator"
tools:context=".MainActivity">
<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:navGraph="#navigation/navigation" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#color/colorPrimary"
app:itemIconTint="#color/colorPrimaryDark"
app:itemTextColor="#color/colorPrimaryDark"
app:menu="#menu/bottom_navigation_menu" />
And this is the bottom nav bar menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/fragment_home"
android:icon="#drawable/ic_home_24px"
android:title="Home" />
<item
android:id="#+id/nav_search"
android:icon="#drawable/ic_search_24px"
android:title="Search" />
<item
android:id="#+id/nav_profile"
android:icon="#drawable/ic_face_24px"
android:title="Profile" />
Navigation.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/navigation"
app:startDestination="#id/homeFragment">
<fragment
android:id="#+id/homeFragment"
android:name="com.puntogris.herewego.home.HomeFragment"
android:label="fragment_home"
tools:layout="#layout/fragment_home" >
<action
android:id="#+id/action_homeFragment_to_profileFragment"
app:destination="#id/profileFragment" />
</fragment>
<fragment
android:id="#+id/profileFragment"
android:name="com.puntogris.herewego.profile.ProfileFragment"
android:label="fragment_profile"
tools:layout="#layout/fragment_profile" >
<action
android:id="#+id/action_profileFragment_to_searchFragment"
app:destination="#id/searchFragment" />
</fragment>
<fragment
android:id="#+id/searchFragment"
android:name="com.puntogris.herewego.search.SearchFragment"
android:label="fragment_search"
tools:layout="#layout/fragment_search" />
Your android:ids do not match.
Your menu XML uses android:id="#+id/fragment_home", but your navigation XML uses android:id="#+id/homeFragment".
These need to be the same name. For example, you could change your menu XML to be
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/homeFragment"
android:icon="#drawable/ic_home_24px"
android:title="Home" />
<item
android:id="#+id/searchFragment"
android:icon="#drawable/ic_search_24px"
android:title="Search" />
<item
android:id="#+id/profileFragment"
android:icon="#drawable/ic_face_24px"
android:title="Profile" />
</menu>
For some reason i can't reselect items in my bottom nav view. How can i enable this feauture?
I have 3 top destination fragments (bottom nav view items): A, B, C
App structure looks like this:
A -> A1
B -> B1 -> B2
C
When user is at fragment B2 he should be able to reselect currently active item, and open fragment B.
Here is related code snippets:
mainActivity.kt
val navView: BottomNavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_main)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.graph_profile, R.id.graph_tools_library,
R.id.graph_settings
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(
navController)
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/graph_profile">
<navigation
android:id="#+id/graph_profile"
app:startDestination="#id/navigation_profile">
<fragment
android:id="#+id/navigation_profile"
android:name="com.example.pocketpsy.presentation.profile.ProfileFragment"
android:label="#string/profile"
tools:layout="#layout/fragment_profile">
<action
android:id="#+id/navigate_to_results"
app:destination="#id/navigation_results" />
</fragment>
<fragment
android:id="#+id/navigation_results"
android:name="com.example.pocketpsy.presentation.results.ResultsFragment"
android:label="#string/results">
<argument
android:name="resultsID"
app:argType="string" />
</fragment>
</navigation>
<navigation
android:id="#+id/graph_tools_library"
app:startDestination="#id/navigation_tools_library">
<fragment
android:id="#+id/navigation_tools_library"
android:name="com.example.pocketpsy.presentation.toolslibrary.ToolsLibraryFragment"
android:label="#string/tools_library"
tools:layout="#layout/fragment_tools_library">
<action
android:id="#+id/navigate_to_description"
app:destination="#id/navigation_description" />
<action
android:id="#+id/navigate_to_tool"
app:destination="#id/navigation_tool" />
</fragment>
<fragment
android:id="#+id/navigation_description"
android:name="com.example.pocketpsy.presentation.description.DescriptionFragment">
<argument
android:name="toolID"
app:argType="string" />
<action
android:id="#+id/navigate_to_tool"
app:destination="#id/navigation_tool"
app:popUpTo="#id/navigation_tools_library" />
</fragment>
<fragment
android:id="#+id/navigation_tool"
android:name="com.example.pocketpsy.presentation.tool.ToolFragment"
android:label="#string/tool"
tools:layout="#layout/fragment_tool">
<argument
android:name="toolID"
app:argType="string" />
<action
android:id="#+id/navigate_to_results"
app:destination="#id/navigation_results" />
</fragment>
<fragment
android:id="#+id/navigation_results"
android:name="com.example.pocketpsy.presentation.results.ResultsFragment"
android:label="#string/results">
<argument
android:name="resultsID"
app:argType="string" />
</fragment>
</navigation>
<navigation
android:id="#+id/graph_settings"
app:startDestination="#id/navigation_settings">
<fragment
android:id="#+id/navigation_settings"
android:name="com.example.pocketpsy.presentation.settings.SettingsFragment"
android:label="fragment_settings"
tools:layout="#layout/fragment_settings" />
</navigation>
</navigation>
bottom_nav_menu.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/graph_profile"
android:icon="#drawable/ic_bottom_bar_profile"
android:title="A" />
<item
android:id="#+id/graph_tools_library"
android:icon="#drawable/ic_bottom_bar_tools_library"
android:title="B"/>
<item
android:id="#+id/graph_settings"
android:icon="#drawable/ic_bottom_bar_settings"
android:title="C" />
</menu>
if you want to unselect specific manu item in nav View the use
navigationView.getMenu().getItem(3).setChecked(false);
if use this in mainActivity or homeactivity and on position 0 item then on start of app there is no menu selected by default
I have 3 top-destination fragments (let's say fragments A, B, C). I can navigate between tabs as expected. However, when i navigate to another fragment from top-destination fragment (fragment A -> fragment A1), I encounter next issue:
When i navigate to another top-destination fragment through bottom nav view, and navigate back (fragment A1 -> fragment B -> fragment A). App opens fragment A1 instead of fragment A and tab B is highlighted as active. Clicking on tab A do nothing.
What is the issue? Here is my setup.
Top-destination fragments are: profile, tools_library, settings
MainActivity.kt
val navView: BottomNavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_main)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_profile, R.id.navigation_tools_library,
R.id.navigation_settings
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(
navController)
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"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#id/nav_view"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/nav_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppTheme.BottomNavigationView"
app:elevation="0dp"
app:itemIconTint="#color/bottom_nav_color_selector"
app:itemTextAppearanceActive="#style/BottomNavigationView.Active"
app:itemTextAppearanceInactive="#style/BottomNavigationView"
app:itemTextColor="#color/bottom_nav_color_selector"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
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/navigation_profile">
<fragment
android:id="#+id/navigation_profile"
android:name="com.example.pocketpsy.presentation.profile.ProfileFragment"
android:label="#string/profile"
tools:layout="#layout/fragment_profile" />
<fragment
android:id="#+id/navigation_tools_library"
android:name="com.example.pocketpsy.presentation.toolslibrary.ToolsLibraryFragment"
android:label="#string/tool"
tools:layout="#layout/fragment_tools_library">
<action
android:id="#+id/navigate_to_description"
app:destination="#id/navigation_description" />
<action
android:id="#+id/navigate_to_tool"
app:destination="#id/navigation_tool" />
</fragment>
<fragment
android:id="#+id/navigation_description"
android:name="com.example.pocketpsy.presentation.description.DescriptionFragment">
<argument
android:name="toolID"
app:argType="string" />
<action
android:id="#+id/navigate_to_tool"
app:destination="#id/navigation_tool"
app:popUpTo="#id/navigation_tools_library" />
</fragment>
<fragment
android:id="#+id/navigation_tool"
android:name="com.example.pocketpsy.presentation.tool.ToolFragment"
android:label="#string/tool"
tools:layout="#layout/fragment_tool">
<argument
android:name="toolID"
app:argType="string" />
<action
android:id="#+id/navigate_to_results"
app:destination="#id/navigation_results" />
</fragment>
<fragment
android:id="#+id/navigation_results"
android:name="com.example.pocketpsy.presentation.results.ResultsFragment"
android:label="#string/results">
<argument
android:name="toolID"
app:argType="string" />
<argument
android:name="resultsID"
app:argType="string" />
</fragment>
<fragment
android:id="#+id/navigation_settings"
android:name="com.example.pocketpsy.presentation.settings.SettingsFragment"
android:label="fragment_settings"
tools:layout="#layout/fragment_settings" />
How i navigate from tools_library fragment to description fragment or tool fragment:
val action: NavDirections
if (toolViewModel.toolDataMap.value!!.isEmpty()) {
action = ToolsLibraryFragmentDirections.navigateToDescription(toolID)
findNavController().navigate(action)
} else {
action = ToolsLibraryFragmentDirections.navigateToTool(toolID)
findNavController().navigate(action)
}
I use single Activity patern in my project.In one of the fragments, let's call it ExploreFragment(), I need to create a FragmentContainerView where several fragments will change. The ExploreFragment() has a search engine and by default displays a MovieGanresFragment() with a list of genres. If I start typing text into the search engine, the fragment changes to MovieByNameFragment() where a list of movies with the name entered by the user is displayed. The question is, how do I implement ExploreFragment() where there will be a container with several fragments and all this using the Navigation component?
I decided to create a ExploreFragment() in the main graph and create a FragmentContainerView in it to switch the two fragments MovieGanresFragment() and MovieByNameFragment() . For switching fragments in ExploreFragment() I use childFragmentManager
private fun switchFragment(movieName: String) {
val searchMovieByNameFragment = SearchMovieByNameFragment.newInstanceSearchMovieByNameFragment(movieName)
openScreenWithMovies(searchMovieByNameFragment)
childFragmentManager.beginTransaction()
.replace(
R.id.fragment_container_explore,
searchMovieByNameFragment
)
.addToBackStack(null)
.commit()
}
It works, but there was another question. How to navigate from the MovieByNameFragment() fragment which is not in the main graph to the MoieDetailsFragment() fragment which is in the main graph and pass the data there?
Thsi is 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/welcome_screen">
<fragment
android:id="#+id/moviesFragment"
android:name="com.example.movies.ui.movies.MoviesFragment"
android:label="Home"
tools:layout="#layout/fragment_movies">
<action
android:id="#+id/action_moviesFragment_to_movieDetailsFragment"
app:destination="#id/movieDetailsFragment"
app:enterAnim="#anim/enter_from_right"
app:exitAnim="#anim/exit_to_right" />
<action
android:id="#+id/action_homeFragment_to_moviesFilterFragment"
app:destination="#id/moviesFilterFragment"
app:enterAnim="#anim/enter_from_top"
app:exitAnim="#anim/exit_to_bottom" />
</fragment>
<fragment
android:id="#+id/movieDetailsFragment"
android:name="com.example.movies.ui.move_details.MovieDetailsFragment"
tools:layout="#layout/fragment_movie_details" >
<argument
android:name="movieId"
app:argType="integer"/>
<argument
android:name="showSavedIcon"
app:argType="boolean"/>
<action
android:id="#+id/action_movieDetailsFragment_self"
app:destination="#id/movieDetailsFragment"
app:enterAnim="#anim/enter_from_right"
app:exitAnim="#anim/exit_to_right" />
</fragment>
<fragment
android:id="#+id/saved_movies"
android:name="com.example.movies.ui.saved_movie.SavedMovieFragment"
android:label="Watch list"
tools:layout="#layout/fragment_saved_movie">
<action
android:id="#+id/action_saved_movies_to_movieDetailsFragment"
app:destination="#id/movieDetailsFragment"
app:enterAnim="#anim/enter_from_right"
app:exitAnim="#anim/exit_to_right" />
</fragment>
<fragment
android:id="#+id/nav_login_fragment"
android:name="com.example.movies.ui.login.LoginFragment"
android:label="fragment_login"
tools:layout="#layout/fragment_login">
<action
android:id="#+id/action_nav_login_fragment_to_homeFragment"
app:destination="#id/moviesFragment"
app:popUpTo="#id/nav_login_fragment"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="#+id/settings"
android:name="com.example.movies.ui.settings.SettingsFragment"
android:label="Settings">
<action
android:id="#+id/action_settings_to_nav_login_fragment"
app:destination="#id/nav_login_fragment"
app:popUpTo="#id/moviesFragment"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="#+id/welcome_screen"
android:name="com.example.movies.ui.welcome_screen.WelcomeScreenFragment"
android:label="fragment_welcome_screen"
tools:layout="#layout/fragment_welcome_screen">
<action
android:id="#+id/action_welcomeScreenFragment_to_nav_login_fragment"
app:destination="#id/nav_login_fragment"
app:popUpTo="#id/welcome_screen"
app:popUpToInclusive="true" />
<action
android:id="#+id/action_welcome_screen_to_homeFragment"
app:destination="#id/homeFragment"
app:popUpTo="#id/welcome_screen"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="#+id/moviesFilterFragment"
android:name="com.example.movies.ui.movie_filter.MoviesFilterFragment"
tools:layout="#layout/fragment_movies_filter">
<action
android:id="#+id/action_moviesFilterFragment_to_homeFragment"
app:destination="#id/moviesFragment"
app:popUpTo="#id/moviesFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="#+id/homeFragment"
android:name="com.example.movies.ui.home.HomeFragment"
android:label="fragment_home"
tools:layout="#layout/fragment_home" >
<action
android:id="#+id/action_homeFragment_to_moviesFragment"
app:destination="#id/moviesFragment" />
<action
android:id="#+id/action_homeFragment_to_movieDetailsFragment"
app:destination="#id/movieDetailsFragment"
app:enterAnim="#anim/enter_from_right"
app:exitAnim="#anim/exit_to_right" />
</fragment>
<fragment
android:id="#+id/explore_fragment"
android:name="com.example.movies.ui.explore.ExploreFragment"
android:label="Explore"
tools:layout="#layout/fragment_explore">
<action
android:id="#+id/action_exploreFragment_to_moviesFragment"
app:destination="#id/moviesFragment" />
</fragment>
</navigation>
This is XML of ExploreFragment()
<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:orientation="vertical"
tools:context=".ui.explore.ExploreFragment">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/home_page_toolbar_color"
android:theme="#style/ToolBarStyle"
android:elevation="4dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.cardview.widget.CardView
android:id="#+id/card_view_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
app:cardCornerRadius="32dp"
app:cardElevation="12dp"
app:layout_constraintTop_toBottomOf="#id/toolbar">
<androidx.appcompat.widget.SearchView
android:id="#+id/search_view"
android:layout_width="match_parent"
android:layout_height="34dp"
android:background="#drawable/background_search_view"
app:iconifiedByDefault="false"
app:queryHint="#string/search_view_hint"
tools:ignore="RtlSymmetry" />
</androidx.cardview.widget.CardView>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragment_container_explore"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="15dp"
android:name="com.example.movies.ui.movie_categories.MovieCategoriesFragment"
app:layout_constraintTop_toBottomOf="#id/card_view_search"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I want to use the navigation and destination system in android so when a menu item in the bottom nav bar is clicked it goes to a fragment.
I created 3 empty fragments and followed this guide to tie the items to the fragments but when I click the menu items, nothing happens.
https://developer.android.com/guide/navigation/navigation-ui
I made sure that the item id from the menu has the same id as the fragment too.
how can I make this work?
Here is my Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navController = findNavController(R.id.nav_host_fragment)
bottom_navigation
.setupWithNavController(navController)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
}
}
This is the activity 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"
android:id="#+id/coordinator"
tools:context=".MainActivity">
<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:navGraph="#navigation/navigation" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#color/colorPrimary"
app:itemIconTint="#color/colorPrimaryDark"
app:itemTextColor="#color/colorPrimaryDark"
app:menu="#menu/bottom_navigation_menu" />
And this is the bottom nav bar menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/fragment_home"
android:icon="#drawable/ic_home_24px"
android:title="Home" />
<item
android:id="#+id/nav_search"
android:icon="#drawable/ic_search_24px"
android:title="Search" />
<item
android:id="#+id/nav_profile"
android:icon="#drawable/ic_face_24px"
android:title="Profile" />
Navigation.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/navigation"
app:startDestination="#id/homeFragment">
<fragment
android:id="#+id/homeFragment"
android:name="com.puntogris.herewego.home.HomeFragment"
android:label="fragment_home"
tools:layout="#layout/fragment_home" >
<action
android:id="#+id/action_homeFragment_to_profileFragment"
app:destination="#id/profileFragment" />
</fragment>
<fragment
android:id="#+id/profileFragment"
android:name="com.puntogris.herewego.profile.ProfileFragment"
android:label="fragment_profile"
tools:layout="#layout/fragment_profile" >
<action
android:id="#+id/action_profileFragment_to_searchFragment"
app:destination="#id/searchFragment" />
</fragment>
<fragment
android:id="#+id/searchFragment"
android:name="com.puntogris.herewego.search.SearchFragment"
android:label="fragment_search"
tools:layout="#layout/fragment_search" />
Your android:ids do not match.
Your menu XML uses android:id="#+id/fragment_home", but your navigation XML uses android:id="#+id/homeFragment".
These need to be the same name. For example, you could change your menu XML to be
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/homeFragment"
android:icon="#drawable/ic_home_24px"
android:title="Home" />
<item
android:id="#+id/searchFragment"
android:icon="#drawable/ic_search_24px"
android:title="Search" />
<item
android:id="#+id/profileFragment"
android:icon="#drawable/ic_face_24px"
android:title="Profile" />
</menu>