I am new to using the navigation component for Android. Most of the examples I have seen online discuss fragment navigation within an activity but, in my case, I want to navigate within a base fragment. In the picture below, I would like to navigate from a login fragment to a signup fragment within the same settings tab but am running into issues and have tried various possible solutions. Any help would be appreciated as I am aware that I can certainly missing something.
java.lang.IllegalArgumentException: Navigation action/destination com.example.animaljournalapp:id/action_userAccountFragment_to_userSignUpFragment cannot be found from the current destination Destination(com.example.animaljournalapp:id/navigation_settings) label=Settings class=com.example.animaljournalapp.ui.settings.UserAccountFragment
I attempt to perform the navigation in the login fragment file through a listener I have attached to a "Sign Up" button:
UserAccountFragment.kt
class UserAccountFragment : Fragment() {
private lateinit var userAccountModel: UserAccountModel
private lateinit var navHostFrag: Fragment
private var _binding: FragmentUserAccountBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
userAccountModel =
ViewModelProvider(this).get(UserAccountModel::class.java)
navHostFrag = SettingsMainFragment()
_binding = FragmentUserAccountBinding.inflate(inflater, container, false)
val root: View = binding.root
val loginButton: Button = root.findViewById(R.id.login_button)
val signupButton: Button = root.findViewById(R.id.signup_button)
loginButton.setOnClickListener{ view: View ->
Toast.makeText(this.context, "Hi", Toast.LENGTH_LONG).show()
}
signupButton.setOnClickListener { view: View ->
val action = UserAccountFragmentDirections.actionUserAccountFragmentToUserSignUpFragment()
Navigation.findNavController(view).navigate(action)
}
return root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
The main activity has a navigation graph of the following:
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_home">
<fragment
android:id="#+id/navigation_home"
android:name="com.example.animaljournalapp.ui.home.HomeFragment"
android:label="#string/title_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/navigation_dashboard"
android:name="com.example.animaljournalapp.ui.dashboard.DashboardFragment"
android:label="#string/title_dashboard"
tools:layout="#layout/fragment_dashboard" />
<fragment
android:id="#+id/navigation_settings"
android:name="com.example.animaljournalapp.ui.settings.UserAccountFragment"
android:label="#string/title_settings"
tools:layout="#layout/fragment_settings_main" />
</navigation>
settings_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/settings_navigation"
app:startDestination="#id/userAccountFragment">
<fragment
android:id="#+id/userAccountFragment"
android:name="com.example.animaljournalapp.ui.settings.UserAccountFragment"
android:label="fragment_user_account"
tools:layout="#layout/fragment_user_account" >
<action
android:id="#+id/action_userAccountFragment_to_userSignUpFragment"
app:destination="#id/userSignUpFragment" />
</fragment>
<fragment
android:id="#+id/userSignUpFragment"
android:name="com.example.animaljournalapp.ui.settings.UserSignUpFragment"
android:label="UserSignUpFragment" />
</navigation>
fragment_settings_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.settings.SettingsMainFragment">
<fragment
android:id="#+id/settings_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/settings_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
Related
I'm sorry for my bad English.
Hello, I'm creating an app that when you click a Button it will create a Button and when clicked, it will navigate to another Fragment. I've already tried making it but for some reason when I click the dynamically created Button, I was sent to the home screen.
Here's my code:
FirstFragment.kt:
class FirstFragment : Fragment() {
private lateinit var binding : FragmentFirstBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_first, container, false)
binding.button.setOnClickListener {
makeButton(senjata1)
}
return binding.root
}
private fun makeButton(Senjata : Senjata) {
val dynamicButton = Button(activity)
dynamicButton.layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
dynamicButton.text = Senjata.name
dynamicButton.setOnClickListener {
findNavController().navigate(R.id.action_firstFragment_to_secondFragment)
}
Senjata.targetView.addView(dynamicButton)
}
}
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" android:id="#+id/navigation"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="#id/mainFragment">
<fragment
tools:layout="#layout/fragment_main"
android:id="#+id/mainFragment"
android:name="com.example.prototipesejarah.MainFragment"
android:label="MainFragment" >
<action
android:id="#+id/action_mainFragment_to_firstFragment"
app:destination="#id/firstFragment" />
</fragment>
<fragment
tools:layout="#layout/fragment_first"
android:id="#+id/firstFragment"
android:name="com.example.prototipesejarah.FirstFragment"
android:label="FirstFragment" >
<action
android:id="#+id/action_firstFragment_to_secondFragment"
app:destination="#id/secondFragment" />
</fragment>
<fragment
android:id="#+id/secondFragment"
android:name="com.example.prototipesejarah.SecondFragment"
android:label="SecondFragment"
tools:layout="#layout/fragment_second" />
</navigation>
Turns out I forgot to add the layout element in the destination's layout file.
fragment_second.xml:
Before:
<LinearLayout 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">
</LinearLayout>
After:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
</LinearLayout>
</layout>
Is there any way to navigate to a certain fragment from another dynamic module and not navigate to the start destination? If not, what are the alternatives?
<fragment
android:id="#+id/loginFragment"
android:name="com.example.feature.login.presentation.LoginFragment"
android:label="LoginFragment">
<action
android:id="#+id/actionLoginToHome"
app:destination="#id/featureHomeNavGraph" />
</fragment>
<include-dynamic
android:id="#+id/featureHomeNavGraph"
app:graphResName="feature_home_nav_graph"
app:moduleName="feature_home" />
While this code works fine, it navigates me to the start destination but I need to navigate to another one.
Solution 1: Navigate to specific fragment and do not use <include-dynamic>
<fragment
android:id="#+id/profileDetailsFragment"
android:name="com.example.feature.profiles.presentation.details.ProfileDetailsFragment"
android:label="Profile Details"
app:moduleName="feature_profiles" />
Solution 2: Create a new graph XML with different start destination.
A good way to do this for embedded nav graphs is to have a blank Navigation Fragment. You get your action to go to this fragment and then send it arguments on where to navigate next. Some sample code:
class NavigatorFragment : Fragment() {
companion object {
const val REQUEST_PAGE_NAME = "REQUEST_PAGE_NAME"
const val PAGE_TYPE_ACTIVATE_CARD = "PAGE_TYPE_ACTIVATE_CARD"
const val PAGE_TYPE_CREDIT_LIMIT = "PAGE_TYPE_CREDIT_LIMIT"
const val PAGE_TYPE_SCC_HUB = "PAGE_TYPE_SCC_HUB"
const val PAGE_TYPE_ABOUT_CARD = "about_card"
const val PAGE_TYPE_MAKE_PAYMENT = "PAGE_TYPE_MAKE_PAYMENT"
fun createBundle(pageName: String) =
Bundle().apply {
putString(REQUEST_PAGE_NAME, pageName)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
when (arguments?.getString(REQUEST_PAGE_NAME)) {
PAGE_TYPE_ACTIVATE_CARD ->
findNavController().navigate(R.id.to_activateSecuredCard)
PAGE_TYPE_CREDIT_LIMIT ->
findNavController().navigate(R.id.to_creditLimit)
PAGE_TYPE_ABOUT_CARD ->
findNavController().navigate(R.id.to_aboutSecuredCard, arguments)
PAGE_TYPE_SCC_HUB ->
findNavController().navigate(R.id.to_sccHub)
PAGE_TYPE_MAKE_PAYMENT ->
findNavController().navigate(R.id.to_sccMakePayment)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding: FragmentSecuredCardNavigatorBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_secured_card_navigator, container, false)
binding.lifecycleOwner = viewLifecycleOwner
if (findNavController()
.currentDestination.toString()
.contains(this.javaClass.name)
){
findNavController().popBackStack()
}
return binding.root
}
}
main navigation:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="#+id/home_dashboard_fragment">
<include app:graph="#navigation/nav_graph_secured_card" />
<!-- rest of navigation graph-->
.....
</navigation>
secured card navigation:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/nav_root_secured_card"
app:startDestination="#id/securedCardNavigator">
<fragment
android:id="#+id/securedCardNavigator"
android:name="com.greendotcorp.securedcard.fragment.NavigatorFragment">
<action
android:id="#+id/to_activateSecuredCard"
app:destination="#+id/activateSecuredCard"
app:popUpTo="#+id/securedCardNavigator"
app:popUpToInclusive="true" />
</fragment>
</navigation>
Navigating to secured card navigation:
findNavController().navigate(R.id.nav_root_secured_card, NavigatorFragment.createBundle(NavigatorFragment.PAGE_TYPE_SCC_HUB))
I am finally adopting Navigation Architecture Components in a new project and I am already encountering some issues that the docs don't seem to address.
With an ActionBar menu setup in the activity, when I navigate to another fragment and then try to use the ActionBar menu I receive
java.lang.IllegalArgumentException: Navigation action/destination X cannot be found from the current destination
It would appear that I must also add actions from all possible destinations to goto all other destinations which seems like overkill, this just cannot be. There must be a solution to this problem that I am not finding.
I intend to open the app which inflates MainActivity and then MainFragment within the fragment element. The MainActivity should still handle top level navigation within the ActionBar. There is absolutely no reason I need to dupe menu click work in every fragment and define destinations to all other areas of the app.
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
private var menu: Menu? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val controller by lazy { findNavController(R.id.fragment_container) }
navController = controller
val appBarConfig by lazy { AppBarConfiguration(navController.graph) }
appBarConfiguration = appBarConfig
setSupportActionBar(toolbar)
setupActionBarWithNavController(navController, appBarConfiguration)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.appbar_menu, menu)
this.menu = menu
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
var direction: NavDirections? = null
when(item.itemId) {
R.id.action_messages -> {
direction = MainFragmentDirections.actionMainFragmentToMessagesFragment()
}
R.id.action_menu -> {
direction = MainFragmentDirections.actionMainFragmentToMessagesFragment()
}
else -> super.onOptionsItemSelected(item)
}
if (direction != null) navController.navigate(direction)
return true
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
activity_main
<?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:id="#+id/card_id_test"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="#color/colorPrimary"
android:elevation="4dp"
android:clipToPadding="false"
app:menu="#menu/appbar_menu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:titleTextColor="#color/white" />
<fragment
android:id="#+id/fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph"
app:layout_constraintTop_toBottomOf="#+id/toolbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainFragment
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
private var mActivity : MainActivity? = null
private var mView: View? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentMainBinding.inflate(inflater, container, false)
mView = binding.root
mActivity = (activity as MainActivity)
return mView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btn_dashboard.setOnClickListener {
findNavController().navigate(
MainFragmentDirections.actionMainFragmentToDashboardFragment())
}
}
}
fragment_main
<?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/content_test"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="Main Fragment"
android:textSize="24dp" />
<com.google.android.material.button.MaterialButton
android:id="#+id/btn_dashboard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="Dashboard" />
</androidx.constraintlayout.widget.ConstraintLayout>
DashboardFragment
class DashboardFragment : Fragment() {
private var _binding: FragmentDashboardBinding? = null
private val binding get() = _binding!!
private var mActivity : MainActivity? = null
private var mView: View? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentDashboardBinding.inflate(inflater, container, false)
mView = binding.root
mActivity = (activity as MainActivity)
return mView
}
}
fragment_dashboard
<?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/content_test"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="Dashboard Fragment"
android:textSize="24dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
nav_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"
android:id="#+id/nav_graph"
app:startDestination="#id/mainFragment">
<fragment
android:id="#+id/mainFragment"
android:name="com.example.appbarnavigation.MainFragment"
android:label="Main" >
<action
android:id="#+id/action_mainFragment_to_messagesFragment"
app:destination="#id/action_messages" />
<action
android:id="#+id/action_mainFragment_to_menuFragment"
app:destination="#id/action_menu" />
<action
android:id="#+id/action_mainFragment_to_dashboardFragment"
app:destination="#id/dashboardFragment" />
</fragment>
<fragment
android:id="#+id/action_messages"
android:name="com.example.appbarnavigation.MessagesFragment"
android:label="Messages" />
<fragment
android:id="#+id/action_menu"
android:name="com.example.appbarnavigation.MenuFragment"
android:label="Menu" />
<fragment
android:id="#+id/dashboardFragment"
android:name="com.example.appbarnavigation.DashboardFragment"
android:label="Dashboard" />
</navigation>
appbar_menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_messages"
android:orderInCategory="1"
android:title="Messages"
android:icon="#drawable/ic_message"
app:showAsAction="always"/>
<item
android:id="#+id/action_menu"
android:orderInCategory="2"
android:title="Menu"
android:icon="#drawable/ic_menu"
app:showAsAction="always"/>
</menu>
This was resolved by defining and using global actions.
<?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/mainFragment">
<fragment
android:id="#+id/mainFragment"
android:name="com.example.appbarnavigation.MainFragment"
android:label="Main" >
<action
android:id="#+id/action_mainFragment_to_dashboardFragment"
app:destination="#id/dashboardFragment" />
</fragment>
<fragment
android:id="#+id/action_messages"
android:name="com.example.appbarnavigation.MessagesFragment"
android:label="Messages" />
<fragment
android:id="#+id/action_menu"
android:name="com.example.appbarnavigation.MenuFragment"
android:label="Menu" />
<fragment
android:id="#+id/dashboardFragment"
android:name="com.example.appbarnavigation.DashboardFragment"
android:label="Dashboard" />
<action android:id="#+id/action_global_action_messages" app:destination="#id/action_messages" />
<action android:id="#+id/action_global_action_menu" app:destination="#id/action_menu" />
</navigation>
and in the MainActivity
override fun onOptionsItemSelected(item: MenuItem) = when(item.itemId) {
R.id.action_messages -> {
navController.navigate(R.id.action_global_action_messages)
true
}
R.id.action_menu -> {
navController.navigate(R.id.action_global_action_menu)
true
}
// This is used for menu buttons or anything not explicitly defined here
else -> {
super.onOptionsItemSelected(item)
}
}
I want to use Navigation in my app.
declared in main_activity
<?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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- Main content -->
<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/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
then I want to go from Fragment1 to Fragment2 using action
UPDATE I am added more code
class LoginFragment2 : Fragment(){
private lateinit var viewModel : LoginViewModel2
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fr_login, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
}
private fun initViews() {
btn_registration.setOnClickListener {
// Navigation.findNavController(it).navigate(R.id.action_loginFragment2_to_newTypeAccountFragment)
// navController = Navigation.findNavController(view)
// findNavController(it).navigate(R.id.action_loginFragment2_to_newTypeAccountFragment)
this.findNavController().navigate(R.id.action_loginFragment2_to_newTypeAccountFragment)
}
}
I tried several options (but not one did not help me)
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app.peshkariki, PID: 22658
java.lang.IllegalStateException: View androidx.constraintlayout.widget.ConstraintLayout{ca39b84
V.E...... ........ 0,0-720,1360} does not have a NavController set
how to work with it correctly?
Navigation graph (In fact, it is very large, but I will post a small part related to this Fragment)
<?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/mainActivity">
<fragment
android:id="#+id/loginFragment2"
android:name="com.app.peshkariki.newPesh.ui.login.LoginFragment2"
android:label="LoginFragment2"
tools:layout="#layout/fr_login">
<action
android:id="#+id/action_loginFragment2_to_newTypeAccountFragment"
app:destination="#id/newTypeAccountFragment" />
</fragment>
</navigation>
You called NavHostFragment but you don't need to.
Change it to
btn_registration.setOnClickListener {
this.findNavController()
.navigate(R.id.action_loginFragment2_to_newTypeAccountFragment)
}
Put this in onViewCreated:
val navHostFragment = supportFragmentManager.findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
Also you might wanna do this course
I am using jetpack navigation in two different activities each with its navigation host. I have Main activity which everything just works fine and Setup activity which have 2 fragments, one has a button which should navigate to other fragment when clicked .
The activity's code is as follows:
class SetupActivity : AppCompatActivity() {
private val navController by lazy { findNavController(R.id.nav_host_fragment) }
private lateinit var appBarConfig: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DataBindingUtil.setContentView<ActivitySetupBinding>(this, R.layout.activity_setup)
setSupportActionBar(toolbar)
appBarConfig = AppBarConfiguration(navController.graph)
setupActionBarWithNavController(navController, appBarConfig)
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfig) || super.onSupportNavigateUp()
}
}
Below is activity's xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".ui.SetupActivity"
tools:showIn="#layout/activity_setup">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/setup" />
</androidx.constraintlayout.widget.ConstraintLayout>
Below is code of first fragment which is also a start Destination
class ConfirmClassFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding = FragmentConfirmClassBinding.inflate(inflater, container, false)
binding.fragment = this
return binding.root
}
fun navigate() {
toast("clicked") //this get called
val direction = ConfirmClassFragmentDirections.actionConfirmToSetup()
findNavController().navigate(direction) //THE PROBLEM IS HERE
//findNavController().navigate(R.id.setup)
}
}
I am using data binding to call fun navigate() as below:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="fragment"
type="com.nux.ui.fragments.ConfirmClassFragment" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="#dimen/spacing_middle">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="#{() -> fragment.navigate()}"
android:text="#string/continue_" />
</LinearLayout>
</layout>
and this how navigation xml looks like:
<?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/setup"
app:startDestination="#id/confirm">
<fragment
android:id="#+id/setup"
android:name="com.nux.ui.fragments.SetInfoFragment"
android:label="#string/setup"
tools:layout="#layout/fragment_set_info" />
<fragment
android:id="#+id/confirm"
android:name="com.nux.ui.fragments.ConfirmClassFragment"
android:label="#string/data_confirmation"
tools:layout="#layout/fragment_confirm_class">
<action
android:id="#+id/action_confirm_to_setup"
app:destination="#id/setup" />
</fragment>
</navigation>
When I click button fun gets called but nothing happens! What could be wrong?
From the code i can see you have the same id for 3 elements in the navigation graph.
#id/setup should only be used once and please change the name of the navigation graph from setup to something else.