How to replace a fragment in jetpack navigation component? - android

val action = LoginFragmentDirections.actionLoginFragmentToHomeFragment(
User(
_binding.emailEt.editText?.text.toString(),
_binding.passwordEt.editText?.text.toString()
)
)
findNavController().navigate(action)
This is my Button press action
<?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/loginFragment">
<fragment
android:id="#+id/loginFragment"
android:name="com.example.passion.ui.LoginFragment"
android:label="fragment_logins"
tools:layout="#layout/fragment_logins">
<action
android:id="#+id/action_loginFragment_to_homeFragment"
app:destination="#id/homeFragment" />
</fragment>
<fragment
android:id="#+id/homeFragment"
android:name="com.example.passion.ui.HomeFragment"
android:label="fragment_home"
tools:layout="#layout/fragment_home" >
<argument
android:name="user"
app:argType="com.example.passion.data.models.User"
app:nullable="true"
android:defaultValue="#null" />
</fragment>
</navigation>
This is my navigation graph
Everytime I press button. it adds the fragment. I want to replace it with HomeFragment
Any help would be appreciated!. thanks

Related

navigation destination is unknown to this NavController in DashboardFragment

Error which I am getting like as below
java.lang.IllegalArgumentException: navigation destination com.actofitSmartScale:id/action_DashboardFragment_to_nav_measurements is unknown to this NavController
at com.actofit.smartscale.dashboard.DashboardFragment.gotoMeasurements(DashboardFragment.java:450)
Call from DashboardFragment
DashboardFragmentDirections.ActionDashboardFragmentToNavMeasurements action =
DashboardFragmentDirections.actionDashboardFragmentToNavMeasurements(userID);
findNavController(requireView()).navigate(action);
nav_smart.xml
<fragment
android:id="#+id/dashboardFragment"
android:name="com.actofit.smartscale.dashboard.DashboardFragment"
android:label="dashboardFragment"
tools:layout="#layout/fragment_dashboard">
<action
android:id="#+id/action_DashboardFragment_to_nav_measurements"
app:destination="#id/nav_measurements">
<argument
android:name="user_id"
app:argType="string"
app:nullable="false" />
</action>
</fragment>
<include app:graph="#navigation/nav_measurements" />
nav_measurments.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/nav_measurements"
app:startDestination="#id/measurementHomeFragment">
<fragment
android:id="#+id/measurementHomeFragment"
android:name="com.actofit.smartscale.measurements.MeasurementHomeFragment"
android:label="fragment_measurement_home"
tools:layout="#layout/fragment_measurement_home"/>

How to add a fragment from external library/framework?

I am trying to add a fragment which has implementation done as part of an external framework. Need to include/reference the fragment in the running application. How this can be done?
below is the navigation XML for reference.
<?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"
app:startDestination="#id/officeFragment">
<fragment
android:id="#+id/officeFragment"
android:name="com.sample.office.OfficeFragment"
android:label="#string/office">
<argument
android:name="officeId"
app:argType="string"
app:nullable="false" />
<action
android:id="#+id/viewEmployees"
app:destination="#id/profileListFragment"/>
</fragment>
<fragment
android:id="#+id/profileListFragment"
android:name="com.externallibrary.component.people.ui.profilelist.ProfileListFragment"
android:label="#string/people">
<argument
android:name="officeId"
android:defaultValue="#null"
app:argType="string"
app:nullable="true" />
</fragment>
</navigation>

How to make bottom nav view items reselectable? Android

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

How to navigate previous fragment without restarting it with NavController?

My app flow A fragment to B fragment :
A -> B(findNavController().navigate(R.id.action_AFragment_to_BFragment))
When I press back arrow from B fragment :
A fragment not resume from resume state but it was restarted(findNavController().popBackStack())
here is my code:
<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/AFragment">
<fragment
android:id="#+id/AFragment"
android:name=".AFragment"
android:label="#string/a_fragment_label"
tools:layout="#layout/fragment_a">
<action
android:id="#+id/action_AFragment_to_BFragment"
app:popUpToSaveState="true"
app:destination="#id/BFragment" />
</fragment>
<fragment
android:id="#+id/BFragment"
android:name=".BFragment"
android:label="#string/b_fragment_label"
tools:layout="#layout/fragment_b">
<action
android:id="#+id/action_BFragment_to_AFragment"
app:popUpToSaveState="true"
app:destination="#id/AFragment"
app:popUpTo="#+id/AFragment"
app:popUpToInclusive="false"/>
</fragment>
</navigation>

Navigation Architecture Component - DestinationFragmentArgs is not generated

I have this in app gradle:
apply plugin: 'androidx.navigation.safeargs'
implementation 'android.arch.navigation:navigation-fragment-ktx:1.0.0'
implementation 'android.arch.navigation:navigation-ui-ktx:1.0.0'
and this in the project gradle:
classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0'
the navigation 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/navigation_graph"
app:startDestination="#id/loginPhoneNumberFragment">
<fragment
android:id="#+id/loginPhoneNumberFragment"
android:name="...fragments.LoginPhoneNumberFragment"
android:label="#string/login_activity_title"
tools:layout="#layout/fragment_login_phone_number">
<action
android:id="#+id/action_loginPhoneNumberFragment_to_loginCodeFragment"
app:destination="#id/loginCodeFragment">
<argument
android:name="prefix"
app:argType="string" />
<argument
android:name="phone_number"
app:argType="string" />
</action>
</fragment>
<fragment
android:id="#+id/loginCodeFragment"
android:name="...LoginCodeFragment"
android:label="#string/login_activity_title"
tools:layout="#layout/fragment_login_code" />
</navigation>
LoginPhoneNumberFragment:
val action = LoginPhoneNumberFragmentDirections.actionLoginPhoneNumberFragmentToLoginCodeFragment(prefix, phoneNumber)
view?.findNavController()?.navigate(action)
LoginCodeFragment:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val prefix = LoginCodeFragmentArgs.fromBundle(arguments).prefix //LoginCodeFragmentArgs is not recognized
}
In the LoginPhoneNumberFragment it creates the "LoginPhoneNumberFragmentDirections" class, but on the destination class, LoginCodeFragment, it doesn't recognize "LoginCodeFragmentArgs".
Can someone please tell me what am I missing?
(I cleaned and rebuilded, and tried Invalidate caches...)
Ok, so after a lot of searching I found out my mistake -
the arguments should be on the Destination fragment, and not on the starting one:
<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_graph"
app:startDestination="#id/loginPhoneNumberFragment">
<fragment
android:id="#+id/loginPhoneNumberFragment"
android:name="...fragments.LoginPhoneNumberFragment"
android:label="#string/login_activity_title"
tools:layout="#layout/fragment_login_phone_number">
<action
android:id="#+id/action_loginPhoneNumberFragment_to_loginCodeFragment"
app:destination="#id/loginCodeFragment">
</action>
</fragment>
<fragment
android:id="#+id/loginCodeFragment"
android:name="...fragments.LoginCodeFragment"
android:label="#string/login_activity_title"
tools:layout="#layout/fragment_login_code" >
<argument
android:name="prefix"
app:argType="string"
android:defaultValue="888" />
<argument
android:name="phone_number"
app:argType="string"
android:defaultValue="88888888"/>
</fragment>
</navigation>
You can also add it manually via the navigation graph design - press on the destination fragment and press "+" on the arguments section, it will add it to the text file.
The argument should be in the destination fragment as follows instead of inside the action in source fragment
<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_graph"
app:startDestination="#id/loginPhoneNumberFragment">
<fragment
android:id="#+id/loginPhoneNumberFragment"
android:name="...fragments.LoginPhoneNumberFragment"
android:label="#string/login_activity_title"
tools:layout="#layout/fragment_login_phone_number">
<action
android:id="#+id/action_loginPhoneNumberFragment_to_loginCodeFragment"
app:destination="#id/loginCodeFragment"/>
</fragment>
<fragment
android:id="#+id/loginCodeFragment"
android:name="...LoginCodeFragment"
android:label="#string/login_activity_title"
tools:layout="#layout/fragment_login_code">
<argument
android:name="prefix"
app:argType="string" />
<argument
android:name="phone_number"
app:argType="string" />
</fragment>
</navigation>

Categories

Resources