I am trying to navigation from DialogFragment to Fragment in Navigation Component, but getting weird result.
When I navigate from DialogFragment to Fragment, background fragment is changing to target fragment with current dialog on top of it, instead of just moving to target fragment.
Here is 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/home"
app:startDestination="#+id/titleScreen">
<fragment
android:id="#+id/titleScreen"
android:name="com.example.android.navigationadvancedsample.homescreen.Title"
android:label="#string/title_home"
tools:layout="#layout/fragment_title">
<action
android:id="#+id/action_title_to_about"
app:destination="#id/aboutScreen"/>
</fragment>
<dialog
android:id="#+id/aboutScreen"
android:name="com.example.android.navigationadvancedsample.homescreen.About"
android:label="#string/title_about"
tools:layout="#layout/fragment_about">
<action
android:id="#+id/action_aboutScreen_to_register"
app:destination="#id/register" />
</dialog>
<fragment
android:id="#+id/register"
android:name="com.example.android.navigationadvancedsample.formscreen.Register"
android:label="fragment_leaderboard"
tools:layout="#layout/fragment_leaderboard" />
</navigation>
Why I am getting this behavior or how to fix it?
By fixing I mean normal dialog behavior. Say, I have a dialog D on top of a fragment A and move to a fragment B from a button on D, the screen should show B. And when I pop back from B, it should go to previous stage of D on top of A.
Thanks #musooff for filing this bug
This problem was fixed on Navigation 2.1.0-alpha06, along with others dialog inconsistencies like back button when Dialog is popped.
However, update to 2.1.0-beta02 or higher if you can.
You could use
view.getDialog().dismiss();
after navigate to B. But in that way, dialog won't be visible when you came back to A fragment.
If you really want it to be visible, maybe you should try to use Fragment and pretend it to be Dialog. Like in these example with activity link.
Related
I have a fragment in bottom navigation when try to launch new fragment with same id using navigation controller instead of launching new fragment it redirects me to bottom navigation tab.
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/home_navigation"
app:startDestination="#id/splashFragment">
<fragment
android:id="#+id/baseTabsFragment"
android:name="com.abc.abc.fragment.BaseTabsFragment"
android:label="BaseTabsFragment"
tools:layout="#layout/fragment_common_tabs">
<action
android:id="#+id/action_to_baseFragment"
app:destination="#id/baseTabsFragment"
app:launchSingleTop="false" />
</fragment>
</navigation>
And code to navigate.
findNavController().navigate(R.id.action_to_baseFragment)
Here is a link for more details on this
https://issuetracker.google.com/issues/262076827
Update: I want to avoid the code duplication. I will have same fragments with same actions but different id's looking for a better way to do it.
If i understand correctly, you want to navigate to the same fragment and fragment does not refresh.
If you use navigation component in visual interface you need to pull an arrow from your baseFragment onto baseFragment again, with this you will see an arrow like self pointed. If you don't use visual just paste below code and it will be created.
<action
android:id="#+id/action_to_BaseFragment"
app:destination="#id/baseTabsFragment"
app:popUpTo="#id/baseTabsFragment"
app:popUpToInclusive="true" />
We are using this way because if we want system to navigate, it needs different location then previous, as long as we using same fragment we need to pop the old one.
It happened due to bottom menu. In this case you need to call programmatically to click on that bottom button.
Replace
findNavController().navigate(R.id.action_to_baseFragment)
to
navController.navigate(
R.id.base_graph, null,
NavOptions.Builder().setPopUpTo(navController.graph.startDestinationId, true).build()
)
Main issue: a fragmentcontainerview works without me wanting it to.
Explanation: I have a fragmentcontainer view in an activity.It is a DialogFragment navigation graph, I want it to only shown when I prompt it but it gets shown when activity is started.
Code in activity xml:
<androidx.fragment.app.FragmentContainerView
android:id="#+id/dialogNavigation"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
app:defaultNavHost="false"
app:navGraph="#navigation/nav_dialog"
tools:layout="#layout/tutorial_dialog_start" />
Setting its visibility gone doesnt help and I couldnt find any other solution
Edit:
Solution 1:
If there's 2 navgraphs: 1 for fragments, 1 for dialogs. Merge them and use actions to navigate to dialogs from specific fragment.
Solution 2:
Create an empty dialog and have it as the first dialog showed in FragmentContainerView, when you want to show the actual dialogs navigate from the empty dialog to the actual dialog
I'm using navigation component
'androidx.navigation:navigation-fragment-ktx:2.3.3'
'androidx.navigation:navigation-ui-ktx:2.3.3'
I don't understand why when I'm navigating from my startDestination to the next Fragment
I get a short blinking and I see the previous activity for a couple of millisec.
This doesn't happen when I'm navigating to different fragments.
This happens with and without the navigation animations.
Tried with no previous Activity in stack and it shows the OS home screen.
The navigation.xml file looks like this:
<fragment
android:id="#+id/barcodeScannerFragment"
android:name="com.sightplan.sightplanmobile.feature.barcode_scanner.BarcodeScannerFragment"
android:label="#string/receive_package_barcode_input_view_header_param_title"
tools:layout="#layout/barcode_scanner_fragment_layout">
<action
android:id="#+id/open_receive_package_details"
app:destination="#id/receivePackageDetailsFragment"
app:enterAnim="#anim/slide_left_anim"
app:exitAnim="#anim/wait_anim"
app:popEnterAnim="#anim/wait_anim"
app:popExitAnim="#anim/slide_right_anim" />
</fragment>
<fragment
android:id="#+id/receivePackageDetailsFragment"
android:name="com.sightplan.sightplanmobile.packages.receive_package.ReceivePackageDetailsFragment"
android:label="#string/receive_package_activity_on_create_header_bar_title"
tools:layout="#layout/receive_package_details_fragment_layout">
.......
The navigation (full) desgin looks like this:
And the code for navigating from the startDestination to the Receive Package screen is here:
val action = BarcodeScannerFragmentDirections.openReceivePackageDetails()
Navigation.findNavController(it).navigate(action)
Any ideas on how to solve this?
The problem was due to the theme set on my navigation Activity inside the AndroidManifest.xml.
I had a custom AppTheme with android:windowIsTranslucent set to true.
Removing that solved the issue.
First, some clarifications. After looking at a lot of other related questions let's start with what this is not:
This is not about BottomNavigation
This is not about operating the ViewPager using Navigation Components (like this one)
This questions is about how to use Navigation Components, when Viewpager is one of the components.
The situation is having 3 tabs: TabA, TabB, and TabC
Also having 2 extra fragments: FragA, FragB
How do I connect them all so that:
ViewPagerAdapter is handing TabA, TabB, and TabC
AND nav_praph will handle moving from:
TabA --> FragA
TabB --> FragB
TabC --> FragA (not a typo)
Desired UI behavior
First Option: The best I could get working was define the FragHost inside one of the tabs (e.g. TabA) and then navigate to FragA. Problem was the navigation was done INSIDE the tab. Meaning user would still see the tabs on top, and also can still swipe to the other tabs. Not what I wanted.
Here is a diagram of what worked, but is not what I wanted (the red symbolizes the hosting fragment)
Second option: move the fragHost to the very top, and have it contain the ViewPager so it takes up full screen. Then in the nagGraph mention
<navigation
android:id="#+id/nav_graph"
app:startDestination="#id/tab_a"
>
<fragment
android:id="#+id/tab_a"
android:name="com.myapp.home.views.TabA"
android:layout="#layout/tab_a_layout"
>
<action
android:id="#+id/action_tab_a_to_frag_a"
app:destination="#+id/frag_a"
/>
</fragment>
<fragment
android:id="#+id/frag_a"
android:name="com.myapp.FragA"
android:label="details"
android:layout="#layout/frag_a"
/>
This resulted in an IllegalStateException ... at androidx.fragment.app.FragmentStore.addFragment
Some debugging and I saw it was trying to add TabA twice. I assumed both ViewPagerAdapter and Nav Component are using the Fragment manager.
How do I have normal navigation where you can use the tabs, but clicking on one takes you to another full screen experience on top of the tabs?
Figured out the second option I mentioned is the right way to go.
Writing here in case someone else has the same issue.
Make sure your nav_graph is pointing from the containint fragment of the ViewPager and not from the specific fragment the ViewPager is holding.
So not from TabA but from ContainerFragmentA which hosts the ViewPager
<navigation
android:id="#+id/nav_graph"
app:startDestination="#id/view_pager_hosting_frag"
>
<fragment
android:id="#+id/view_pager_hosting_frag"
android:name="com.myapp.home.views.ViewPagerHostingFrag"
android:layout="#layout/view_pager_layout"
>
<action
android:id="#+id/action_tab_a_to_frag_a"
app:destination="#+id/frag_a"
/>
</fragment>
<fragment
android:id="#+id/frag_a"
android:name="com.myapp.FragA"
android:label="details"
android:layout="#layout/frag_a"
/>
Then you can choose the action you want from any of the tabs to go to the right location
This question already has an answer here:
navigation component popUpTo bug
(1 answer)
Closed 2 years ago.
Inside an app I'm building I have used the single activity architecture and decided to use Google's new Navigation component to navigate around the app.
Though it's showing great promise, it has some drawbacks which my question is about one of them.
Assume that we have three fragments which are navigated in order, except that we want to go back to the first one when back button is clicked when we are on the third fragment. Here's how it goes:
<?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_graph.xml"
app:startDestination="#id/firstFragment">
<fragment
android:id="#+id/firstFragment"
android:name="com.hmomeni.navisample.FirstFragment"
android:label="fragment_first"
tools:layout="#layout/fragment_first" >
<action
android:id="#+id/action_firstFragment_to_secondFragment"
app:destination="#id/secondFragment" />
</fragment>
<fragment
android:id="#+id/secondFragment"
android:name="com.hmomeni.navisample.SecondFragment"
android:label="fragment_second"
tools:layout="#layout/fragment_second" >
<action
android:id="#+id/action_secondFragment_to_thirdFragment"
app:destination="#id/thirdFragment"
app:popUpTo="#+id/firstFragment" />
</fragment>
<fragment
android:id="#+id/thirdFragment"
android:name="com.hmomeni.navisample.ThirdFragment"
android:label="fragment_third"
tools:layout="#layout/fragment_third" />
</navigation>
The problem here is that when I want to repeat the navigation for a second time an exception occurs telling me that:
java.lang.IllegalArgumentException: navigation destination
com.hmomeni.navisample:id/action_firstFragment_to_secondFragment is
unknown to this NavController
Further investigation shows that upon hitting back button and returning to the first fragment, the navController.currentDestination still refers to the ThirdFragment which is wrong and it should be FirstFragment.
Any help on this is appreciated.
I was having an issue similar to this question but with circular navigation, where the back stack was not being popped. When navigating from C --> A, I was mistakenly setting the parameter for navigate(int resId) as
R.id.fragmentC
instead of using an action like
R.id.action_c_to_a
I found a somewhat workaround though I wouldn't call it a solution.
To hack around this issue one can create an action from ThirdFragment to itself and then check for navController.currentDestination when navigate is called.
I would not accept this answer for want of a real solution.