How to replace ChildFragmentManager with Navigation Graph in Android - android

I'm working on nested fragment scenario where I'm using a fragment with BottomNavigationView and inside that main fragment I need to load new fragments and these new fragments should replace more fragments within main fragment what contains BottomNavigationView. I'm able to load main fragment using NavigationGraph but not child fragments.
I'm loading main fragment as
<navigation ------- >
<fragment
android:id="#+id/mainTabFragment"
android:name="com.package.MainTabFragment"
android:label="#string/app_name"
tools:layout="#layout/fragment_main_tab"/>
</navigation>
And for Child fragments I'm using fragment manager as:
private fun loadFragment(fragment: Fragment): Boolean {
//switching fragment
childFragmentManager
.beginTransaction()
.replace(R.id.container, fragment)
.commit()
return true
}
MainFragmentGraph:
<?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_landing_graph">
<!-- region added graphs -->
<include app:graph="#navigation/nav_landing_graph" />
<include app:graph="#navigation/nav_graph_main_tab" />
<!-- endregion -->
<fragment
android:id="#+id/mainTabFragment"
android:name="com.package.ui.mainTab.bottomView.MainTabFragment"
tools:layout="#layout/fragment_main_tab">
<action
android:id="#+id/action_landingFrag_to_bottomViewFrag"
app:destination="#id/nav_graph_main_tab" />
</fragment>
</navigation>
nav_graph_main_tab.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_main_tab"
app:startDestination="#id/mainTabFragment">
<fragment
android:id="#+id/mainTabFragment"
android:name="com.package.ui.mainTab.bottomView.MainTabFragment"
android:label="#string/my_health_space"
tools:layout="#layout/fragment_main_tab">
<action
android:id="#+id/action_bottomViewFrag_to_mainFrag"
app:destination="#id/nav_menu_graph" />
</fragment>
<include app:graph="#navigation/nav_menu_graph" />
</navigation>
It would be great if someone can help me to replace it with NavGraphComponent. Thanks.

Related

Navigating between nested graphs starts the enter animation of the fragment, even though the animation is only mentiond in an action

I have a bottomNavigationView that I set up with a nav controller.
The nav Host graph is a navigation graph with 2 nested graphs.
When I navigate between the nested graphs, there is a fragment which is then shown (The fragment which was at the top of the stack of the nested Graph)
The problem id that the fragment is shown with the animation thet was used to navigate to it INSIDE THE NESTED GRAPH.
This is the code for the parent 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/home_nav"
app:startDestination="#id/home_main_nav">
<navigation
android:id="#+id/home_main_nav"
app:startDestination="#id/main_nav">
<include app:graph="#navigation/main_nav" />
</navigation>
<navigation
android:id="#+id/home_notifications_nav"
app:startDestination="#id/notifications_nav">
<include app:graph="#navigation/notifications_nav" />
</navigation>
</navigation>
And this is the code for the nested 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/main_nav"
app:startDestination="#id/mainFragment">
<fragment
android:id="#+id/mainFragment"
android:name="com.scorelate.app.fragments.home.MainFragment"
android:label="fragment_home_main"
tools:layout="#layout/fragment_home_main">
<action
android:id="#+id/action_mainFragment_to_paymentsFragment"
app:destination="#id/paymentsFragment"
app:enterAnim="#anim/slide_in_right"
app:exitAnim="#anim/do_nothing"
app:popExitAnim="#anim/slide_out_right" />
</fragment>
<fragment
android:id="#+id/paymentsFragment"
android:name="com.scorelate.app.fragments.home.PaymentsFragment"
android:label="fragment_payments"
tools:layout="#layout/fragment_payments" />
</navigation>
When the payments fragment is in the main nav, and I navigate to it from the notifications nav, the animation used for it is #anim/slide_in_right
But when the mainFragment (start destination) is in the main nav, the animation used is just a fade animation.
How can I make that the animation for the payments fragment too?

Navigated fragment shows behind the previous fragment in Navigation architecture component jetpack

<?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/restaurantListFragment">
<fragment
android:id="#+id/scanQRFragment"
android:name="com.example.dine.ui.view.home.scan_qr.ScanQRFragment"
android:label="fragment_scan_q_r"
tools:layout="#layout/fragment_scan_q_r" />
<fragment
android:id="#+id/restaurantListFragment"
android:name="com.example.dine.ui.view.home.restaurants.RestaurantListFragment"
android:label="fragment_restaurant_list"
tools:layout="#layout/fragment_restaurant_list" >
<action
android:id="#+id/action_restaurantListFragment_to_restaruntDetailFragment"
app:destination="#id/restaruntDetailFragment"
app:popUpTo="#id/restaurantListFragment" />
</fragment>
<fragment
android:id="#+id/myPlateFragment"
android:name="com.example.dine.ui.view.home.my_plate.MyPlateFragment"
android:label="fragment_my_plate"
tools:layout="#layout/fragment_my_plate" />
<fragment
android:id="#+id/accountFragment"
android:name="com.example.dine.ui.view.home.account.AccountFragment"
android:label="fragment_account"
tools:layout="#layout/fragment_account" />
<fragment
android:id="#+id/restaruntDetailFragment"
android:name="com.example.dine.ui.view.restaurant_detail.RestaruntDetailFragment"
android:label="RestaruntDetailFragment"
tools:layout="#layout/fragment_restarunt_detail" />
</navigation>
Here is the navigation graph file I have used for this navigation fragments.
private fun onItemSelected() {
findNavController().navigate(R.id.action_restaurantListFragment_to_restaruntDetailFragment)
}
I called the `onItemSelected() method on a action, any help would be great. thanks
While Navigating from Restaurant list to RestaurantDetail fragment It comes like this. I have been suffering from this issue so long

How get the same ViewModel,that shared between fragments via "by navGraphViewModels(R.id.main_graph)" in activity?

I have MainActivity with
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph"
...some>
and I Have two fragments. In each fragment i get ViewModel object, that shared beetween fragments:
val viewModel: MyViewModel by navGraphViewModels(R.id.main_graph)
R.id.main_graph is nested navigation into main navigation, that unite two fragments.
How get the same MyViewModel object in MainActivity?
updated
<?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/main_graph"
>
<navigation android:id="#+id/main_graph"
app:startDestination="#id/userListFragment"
>
<fragment
android:id="#+id/userListFragment"
android:name="com.vazheninapps.githubuserwatcher.screens.fragments.UserListFragment"
android:label="fragment_user_list"
tools:layout="#layout/fragment_user_list">
<action
android:id="#+id/action_userListFragment_to_userDetailedFragment"
app:destination="#id/userDetailedFragment"
app:enterAnim="#android:anim/slide_in_left"
app:exitAnim="#anim/fade_out" />
</fragment>
<fragment
android:id="#+id/userDetailedFragment"
android:name="com.vazheninapps.githubuserwatcher.screens.fragments.UserDetailedFragment"
android:label="fragment_user_detailed"
tools:layout="#layout/fragment_user_detailed" />
</navigation>
</navigation>

Navigate from one activity to another with Navigation Component

I am trying to navigate from one navigation graph (with the host fragment on the LoginActivity) to another navigation graph (with the host fragment on the HomeActivity). I know Google is advocating for single activity applications and thus I am only going to be using these two Activities (to keep it minimal).
My login_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/nav_login">
<fragment
android:id="#+id/nav_login"
android:name="your.appname.LoginFragment"
android:label="#string/login_menu"
tools:layout="#layout/fragment_login" >
<action
android:id="#+id/action_nav_login_to_enterCellphone"
app:destination="#id/login_enter_cellphone"
app:popUpTo="#id/nav_login" />
</fragment>
<fragment
android:id="#+id/login_enter_cellphone"
android:name="your.appname.LoginEnterCellphoneFragment"
android:label="#string/enter_cellphone_fragment_label"
tools:layout="#layout/fragment_login_enter_cellphone" >
<action
android:id="#+id/action_enter_cellphone_to_enterOTPFragment"
app:destination="#id/enterOTPFragment"
app:popUpTo="#id/login_enter_cellphone" />
</fragment>
<fragment
android:id="#+id/enterOTPFragment"
android:name="your.appname.EnterOTPFragment"
android:label="#string/enter_otp_label"
tools:layout="#layout/fragment_enter_o_t_p" >
<action
android:id="#+id/action_enterOTPFragment_to_main_navigation"
app:destination="#id/main_navigation"
app:launchSingleTop="false" />
</fragment>
<include app:graph="#navigation/main_navigation" />
</navigation>
And main_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/main_navigation"
app:startDestination="#id/nav_home">
<fragment
android:id="#+id/nav_home"
android:name="your.appname.HomeFragment"
android:label="Home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/nav_profile"
android:name="your.appname.ProfileFragment"
android:label="#string/profile_menu"
tools:layout="#layout/fragment_profile" />
</navigation>
I found this answer and implemented it as follows
private fun navigateToHomeActivity() {
val action = EnterOTPFragmentDirections.actionEnterOTPFragmentToMainNavigation()
findNavController().navigate(action)
(activity as LoginActivity).finish() <-- later commented out
}
but it gives me the following error E/InputMethodManager: prepareNavigationBarInfo() rootView is null
If I comment out the above line the error goes away but it only replaces the current fragment with the HomeFragment.
How do I navigate to another Activity so that the source Activity is removed (Can't navigate back to it) and the Destination Activity is used?
You can define 2 navigation graphs:
ActivityA with navigation Graph A
ActivityB with navigation Graph B
In the GraphA you can define a destination to start ActivityB
<!-- Graph A -->
<navigation
....
<activity
android:id="#+id/activityB"
android:name=".ActivityB"
...>
<argument
.... />
</activity>
</navigation>
Then you can navigate to that activity ( = startActivity(intent)) using it like a destination:
Navigation.findNavController(view).navigate(R.id.activityB);
More info here.

Is it possible to have dynamic destination in Nested Navigation Graph Android?

I have implemented a nested graph in Navigation graph, which is having 2 graphs. In the first graph, there are 3 fragments and in the second graph, there are 2 fragments. Graph 2 is included in graph 1. I want to navigate to (graph 1 step 1) to (graph 2 step 2). We can not define action between two nested fragments. So is there any way by which we can assign the dynamic destination to navigation?
Graph 1
<?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/dashboardFragment">
<fragment
android:id="#+id/dashboardFragment"
android:name="com.navigationgraphexample.fragments.DashboardFragment"
android:label="fragment_dashboard"
tools:layout="#layout/fragment_dashboard" >
<action
android:id="#+id/action_dashboardFragment_to_stepOneFragment2"
app:destination="#id/stepOneFragment" />
<action
android:id="#+id/action_dashboardFragment_to_sub_nav"
app:destination="#id/sub_nav" />
</fragment>
<fragment
android:id="#+id/stepOneFragment"
android:name="com.navigationgraphexample.fragments.StepOneFragment"
android:label="fragment_step_one"
tools:layout="#layout/fragment_step_one">
<action
android:id="#+id/action_stepOneFragment_to_stepTwoFragment"
app:destination="#id/stepTwoFragment" />
</fragment>
<fragment
android:id="#+id/stepTwoFragment"
android:name="com.navigationgraphexample.fragments.StepTwoFragment"
android:label="fragment_step_two"
tools:layout="#layout/fragment_step_two" />
<fragment
android:id="#+id/notificationFragment"
android:name="com.navigationgraphexample.fragments.NotificationFragment"
android:label="fragment_notification"
tools:layout="#layout/fragment_notification" >
<deepLink
android:id="#+id/deepLink"
app:uri="myapp.com/{myargs}"
/>
<argument android:name="myargs"
app:argType="integer"
android:defaultValue="1" />
</fragment>
<include app:graph="#navigation/sub_nav" />
</navigation>
Graph 2
<?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/sub_nav"
app:startDestination="#id/createNewTaskFragment">
<fragment
android:id="#+id/listFragment"
android:name="com.navigationgraphexample.fragments.ListFragment"
android:label="fragment_list"
tools:layout="#layout/fragment_list" />
<fragment
android:id="#+id/createNewTaskFragment"
android:name="com.navigationgraphexample.fragments.CreateNewTaskFragment"
android:label="fragment_create_new_task"
tools:layout="#layout/fragment_create_new_task" >
<action
android:id="#+id/action_createNewTaskFragment_to_listFragment"
app:destination="#id/listFragment" />
</fragment>
</navigation>
I have checked this solution but it is not for the nested graph!
As far as class NavGraph extends NavDestination, you can try the following to change nested graph's startDestination before calling navigate to sub_nav:
val graph = navController.graph.findNode(R.id.sub_nav)
if (graph is NavGraph) {
graph.startDestination = R.id.createNewTaskFragment
}
UPD: Since version 2.4.0 all Navigation artifacts have been rewritten in Kotlin, so the setter should be accessed by it's original name:
graph.setStartDestination(R.id.createNewTaskFragment)

Categories

Resources