Navigation destination is unknown to this NavController - android

When I clicked on the button this thing is happening
navigation destination com.android.example.cameraxbasic:id/action_camera_to_gallery is unknown to this NavController
This is my code in fragment
container.findViewById<ImageButton>(R.id.photo_view_button).setOnClickListener {
Navigation.findNavController(requireActivity(), R.id.fragment_container).navigate(
CameraFragmentDirections.actionCameraToGallery(outputDirectory.absolutePath))
}
This is a full error description

In my case , I am using HomeFragment Having FragmentOne and FragmentTwo in HomeFragment
<?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=".HomeFragment">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="729dp"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentOne"
android:name="com.example.FragmentOne"
android:layout_width="match_parent"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentTwo"
android:name="com.example.FragmentTwo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/fragmentCarosuel" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
my nav_main.xml file is like below:
<?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">
<fragment
android:id="#+id/nav_home"
android:name="com.example.HomeFragment"
android:label="#string/menu_home"
tools:layout="#layout/fragment_home">
<action
android:id="#+id/action_main_to_fragment_three"
app:destination="#id/fragmentThree" />
</fragment>
<fragment
android:id="#+id/fragmentThree"
android:name="com.example.FragmentThree"
android:label="fragment_three"
tools:layout="#layout/fragment_three" >
</fragment>
</navigation>
Now, I am Navigating from FragmentTwo any click event etc.:
NOTE: Please make sure while selection of navigation destingation in navGraph. Here i am using two sub fragment (FragmentOne and FragmentTwo) but my base fragment is HomeFragment. so i have to make action from HomeFragment. If anyone create destination from FragmentOne it is not accesible from HomeFragment and NavController did not identify.
HomeFragmentDirections.ActionMainToFragmentThree nextAction = HomeFragmentDirections.actionMainToFragmentThree();
NavController navController = NavHostFragment.findNavController(this);
navController.navigate(nextAction);
Sorry for poor English. Thanks

Related

Android multi-fragment navigation

I have two different layout for portrait:
<?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=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
and landscape orientation:
<?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=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/container_channel"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/container_messages"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/container_messages"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/container_channel"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I have androidx.navigation:navigation-fragment-ktx:2.4.1 and my app perfectly change fragment in portrait orientation.
I would like to click on the button in the first fragment and change the state in the second
I got something like this:
if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
supportFragmentManager.beginTransaction()
.replace(R.id.container_channel, ChannelsFragment())
.replace(R.id.container_messages, MessagesFragment())
.commit()
} else {
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.container) as NavHostFragment
navController = navHostFragment.navController
}
Is it possible to make different navigation using this library for different orientations?
Is it possible to manage navigation from first fragment in second one using navigation lib?

How to handle Navigation Graph in Nested Fragment of Android

I'm using BottomNavigationView in a fragment and want to show different fragments on tap of each option og that. I'm able to see BottomNavigationView but I'm unable to load any fragment. I'm using below code for that.
res/layout/fragment_main_tab.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">
<fragment
android:id="#+id/nav_menu_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottom_navigation_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/main_menu_nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_navigation_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemBackground="#drawable/bottom_view_selector"
app:labelVisibilityMode="labeled"
app:layout_anchorGravity="bottom"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="#menu/bottom_nav_menu"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
res/navigation/main_menu_nav_graph.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"
android:id="#+id/main_menu_nav_graph"
app:startDestination="#id/navigation_main_tab_fragment">
<fragment
android:id="#+id/navigation_main_tab_fragment"
android:name="com.pkg.ui.main.MainTabFragment"
android:label="#string/app_name"/>
</navigation>
MainTabFragment.kt
binding.bottomNavigationView.setOnItemSelectedListener {
when (it.itemId) {
R.id.home -> {
findNavController().navigate(R.id.nav_menu_to_main_fragment)
}
R.id.wallet -> {
findNavController().navigate(R.id.nav_menu_to_main_fragment)
}
else -> {
null
}
}
true
}
res/navigation/nav_menu_graph.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"
android:id="#+id/nav_menu_graph"
app:startDestination="#id/nav_menu_to_main_fragment">
<fragment
android:id="#+id/nav_menu_to_main_fragment"
android:name="com.pkg.ui.main.MainFragment"
android:label="#string/app_name" />
</navigation>
It always shows blank without MainFragment or either it gets crashed. Can anyone please check once and highlight if I'm making any mistake? Thanks in advance.
I think you should try this MainTabFragment
(supportFragmentManager.findFragmentById(R.id.nav_menu_fragment) as NavHostFragment).navController.apply {
binding.bnvAppBottomNav.setupWithNavController(this)
addOnDestinationChangedListener { _, destination, _ ->
binding.bnvAppBottomNav.visibility = when (destination.id) {
R.id.Home,
R.id.Wallet,
R.id.Profile -> GONE
else -> VISIBLE
}
}
}
And also try this in res/layout/fragment_main_tab.xml
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_menu_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottom_navigation_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/main_menu_nav_graph" />
Hope this give you some hint

Fragment not switching using FragmentContainerView

I simply want to use bottomNavigation with Navigation Component. I tried multiple ways but fragment not switching . Only BottomNavigation display's
I have a running sample that uses fragment instead of FragmentContainerView. But I don't know why it's too complex to use the latest techtiques
DashboardActivity
#AndroidEntryPoint
class DashboardActivity : PBActivity(R.layout.activity_dashboard) {
val binding: ActivityDashboardBinding by viewbind()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val appBarConfiguration: AppBarConfiguration = AppBarConfiguration.Builder(
R.id.rankingFragment, R.id.homeFragment, R.id.profileFragment
).build()
setSupportActionBar(binding.toolbar)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
/*val navView = findViewById<BottomNavigationView>(R.id.bottom_nav)
NavigationUI.setupWithNavController(navView,navController)*/
///binding.navigationBb.setupWithNavController(navController)
///binding.toolbar.setupWithNavController(navController,null)
//binding.navHostFragment.s
binding.toolbar.setupWithNavController(navController,appBarConfiguration)
///binding.bottomNav.setupWithNavController(navController)
NavigationUI.setupWithNavController(binding.bottomNav, navController)
///NavigationUI.setupWithNavController(binding.bottomNav,navController)
}
}
activity_dashboard.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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="0dp">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.appcompat.widget.Toolbar>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="match_parent"
app:menu="#menu/dashboard_nav_menu"
android:background="?android:attr/windowBackground"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
nav_graph.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/nav_graph"
app:startDestination="#id/homeFragment">
<fragment
android:id="#+id/homeFragment"
tools:layout="#layout/fragment_home"
android:name="uk.co.planetbeyond.game_show_app.presentation.ui.main.fragments.HomeFragment"
android:label="HomeFragment" />
<fragment
android:id="#+id/rankingFragment"
tools:layout="#layout/fragment_ranking"
android:name="uk.co.planetbeyond.game_show_app.presentation.ui.main.fragments.RankingFragment"
android:label="RankingFragment" />
<fragment
android:id="#+id/profileFragment"
tools:layout="#layout/fragment_profile"
android:name="uk.co.planetbeyond.game_show_app.presentation.ui.main.fragments.ProfileFragment"
android:label="ProfileFragment" />
</navigation>
dashboard_nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/rankingFragment"
android:icon="#drawable/rankings_button_selected"
android:title="Ranking" />
<item
android:id="#+id/homeFragment"
android:icon="#drawable/home_button_selected"
android:title="#string/title_home" />
<item
android:id="#+id/profileFragment"
android:icon="#drawable/profile_icon_selected"
android:title="Profile" />
</menu>
The problem is not in the navigation components, your code looks fine regarding it; but that your main layout has a 0 size:
You need to set the root layout to match parent:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
Side note: the fragments will draw behind the toolbar as it constraints to the parent top edge; The same for the bottom part.
To fix this constraint it to the toolbar:
In the FragmentContainerView Replace:
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
With:
app:layout_constraintTop_toBottomOf="#+id/toolbar"
app:layout_constraintBottom_toTopOf="#+id/bottom_nav"

Using nav host fragment and bottom navigation view inside fragment?

I have nav host fragment and bottom navigation view inside home fragment as below
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="home.HomeFragment2">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/homeNavHost"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/bottomMenu"
app:layout_constraintEnd_toEndOf="parent"
app:navGraph="#navigation/staging_menu_navigation1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
The menu as
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/staging_dashboard_nav_graph"
android:icon="#drawable/ic_home"
android:title="#string/menu_dashboard" />
<item
android:id="#+id/staging_offer_nav_graph"
android:icon="#drawable/ic_offer"
android:title="#string/menu_offers" />
<item
android:id="#+id/staging_profile_nav_graph"
android:icon="#drawable/ic_profile"
android:title="#string/menu_profile" />
</menu>
The navigation graph as
<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/staging_menu_navigation"
app:startDestination="#id/dashboardFragment3">
<include app:graph="#navigation/staging_dashboard_nav_graph" />
<include app:graph="#navigation/staging_offer_nav_graph" />
<include app:graph="#navigation/staging_profile_nav_graph" />
<fragment
android:id="#+id/dashboardFragment3"
android:name="com.octave.dashboard.DashboardFragment"
android:label="DashboardFragment" />
</navigation>
The other graphs are as
<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/staging_dashboard_nav_graph"
app:startDestination="#id/dashboardFragment">
<fragment
android:id="#+id/dashboardFragment"
android:name="com.octave.dashboard.DashboardFragment"
android:label="dashboard_fragment"
tools:layout="#layout/dashboard_fragment" />
</navigation>
Offer graph
<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/staging_offer_nav_graph"
app:startDestination="#id/offersFragment">
<fragment
android:id="#+id/offersFragment"
android:name="com.octave.offers.OffersFragment"
android:label="offers_fragment"
tools:layout="#layout/offers_fragment" />
</navigation>
Profile graph
<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/staging_profile_nav_graph"
app:startDestination="#id/profileFragment">
<fragment
android:id="#+id/profileFragment"
android:name="com.octave.profile.ProfileFragment"
android:label="profile_fragment"
tools:layout="#layout/profile_fragment" />
In my home fragment I am setting up as
binding.bottomMenu.setupWithNavController(Navigation.findNavController(requireActivity(), R.id.homeNavHost))
When I tap on bottom menu items the fragment doesn't change.
What is wrong over here?
If you are trying to create another nav graph with the bottom navigation bar that is already a part of the default nav graph, you first need to change the defaultNavHost value to false in XML of wherever your nav host fragment is in. then find NavHost to get NavController:
val navHost = childFragmentManager.findFragmentById(R.id.${yourNavHostFragment} as NavHostFragment
val navController = navHost.navController
view.findViewById<BottomNavigationView>(R.id.bottomNavigationView).setupWithNavController(navController!!)

How to navigate back to the master screen from the details with Nav controller on Android

I have the following nav_graph 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"
app:startDestination="#id/users_fragment"
android:id="#+id/nav_graph">
<fragment
android:id="#+id/users_fragment"
android:name="com.package.UsersFragment"
tools:layout="#layout/users_fragment"
android:label="UsersFragment">
<action
android:id="#+id/action_users_fragment_to_profile_fragment"
app:destination="#id/profile_fragment"
app:popUpTo="#id/users_fragment"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="#+id/profile_fragment"
android:name="com.package.ProfileFragment"
android:label="ProfileFragment">
<argument
android:name="userId"
app:argType="string" />
</fragment>
</navigation>
The main activity xml is:
<?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">
<data>
<variable
name="viewModel"
type="com.package.UsersViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:background="#color/colorPrimary" />
</com.google.android.material.appbar.AppBarLayout>
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/app_bar_layout"
app:navGraph="#navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
To navigate to the details I call:
val action = UsersFragmentDirections
.actionUsersFragmentToProfileFragment(
userId = user.userId,
)
navController.navigate(action)
where UsersFragmentDirections is generated by the safe-args plugin.
The problem is that when I press back the master fragment is not shown: the activity is closed.
If in the action I use app:popUpToInclusive="false" then the back button does not work anymore.
What should I do to be able to go to the UsersFragment from the ProfileFragment when the user press back?
You're popping users fragment while moving to profile fragment. So when you press back, there is nothing in the backstack and hence activity finishes..
So, to fix this issue you have two options:
1) Manually re-open/navigate users fragment
Or
2) Remove these two lines
app:popUpTo="#id/users_fragment"
app:popUpToInclusive="true"

Categories

Resources