Android navigation component- With Login screens - android-architecture-navigation

When dealing with login screens, I am trying to work out the better approach - either execute navigation "action" to go to login fragment on first use (and hide back button to actual app), or start a new login activity (with its own nav graph). For the first approach (just using navigation components), I do not know the way to remove the back button without a hack "hide". I tried using navoptions, setpopupto etc., but it does not work. Code below:
val navOptions = NavOptions.Builder()
.setPopUpTo(R.id.home_fragment, true)
.build()
host?.navController?.navigate(R.id.action_global_signUpFragment_dest, null, navOptions)
Two questions then:
1) How to properly handle login transition with just navigation component?
2) Is starting a new login activity, with separate nav graph, a better idea?

I think the first approach is better.
To hide the 'back' button on your toolbar inside signUpFragment you can use AppBarConfiguration, and customize which destinations are considered top-level destinations.
For example:
val appBarConfiguration = AppBarConfiguration.Builder(setOf(R.id.home_fragment, R.id.signUpFragment_dest)).build()
NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration)
This way home_fragment and signUpFragment_dest will be considered top-level destinations, and won't have back button on toolbar.

Another option for solving the back button problem is how I did it here. Also, rather than show/hide the bottom nav bar, I have two NavHostFragment, one main full screen one, and one contained within the home fragment (above the bottom nav bar).
When I want to navigate to a full screen view I call this extension function,
fun Fragment.findMainNavController(): NavController =
Navigation.findNavController(activity!!, R.id.nav_host_fragment)
then navigate via the main graph.
This makes sense conceptually to me, to have parent and child nav graphs.

Related

SwiftUI delete Navigation Stack

When starting my app for the first time, a little setup is required. After this setup, the user should then come to the MainView.
Now I want it to be so that the user cannot jump back to the last setup step as soon as he reaches the MainView.
All the solutions I can find is to simply remove the back button. But this is not enough for me, I'm currently working with tvOS, there is a back Button on his remote. If he then presses this, he should ideally just come back to the tvOS home screen.
Is there any possibility to delete the complete navigation stack or something similar with the same result?
You can replace your entire view hierarchy at the parent level (above your NavigationView if a given condition is true:
var body : some View {
if setup {
//parent component of views for once setup is done
MainView()
} else {
//parent component of the setup views (including a NavigationView)
SetupScreens()
}
}
So, on the final setup screen, set setup to true (this should probably be stored in an ObservableObject that each view can access [possible via an .environmentObject]) and the NavigationView will be destroyed and the hierarchy will be replaced with MainView.

Watchkit popToRootController not working

I am using a vertical page direction on my watch app, and I have a button that opens a new interface, which opens the third interface also from a button, this is done by using the modal view, and in the third interface i am calling popToRootController, because i want to go back to the first interface, but this is not working, have anyone same issue?
You need to use dismiss if you present view controllers modally using presentControllerWithName.
You can use popToRootController or popController if you present the view controllers hierarchically using pushControllerWithName.
You can read more on the Apple Interface Navigation guide.
In your example if you want to dismiss twice, you will have to pass a delegate or closure with the context to your second controller. Then you can call the delegate method or closure after dismiss() on the third controller. The implementation of the delegate method or closure will be another dismiss().

Repositioning Master View display button in Split View Controller

As you know, split view controller hides the master view and displays detail view in full screen mode in ipad. In the full screen mode, ios creates a bar button for the master view on the navigation bar. My question is, is it possible to reposition that button to the far right instead of left? Because my detail view is embedded inside a navigation view controller and there are severals views associated with it. It gets confusing when master view is hidden and the detail view has button to go back to the previous view.
In above screencap, "Category" is a button to display the masterview and "List of Events" is a back button. If you have better way to handle this situation, please feel free to suggest.
Yes, you can do it just send a NotificationCenter.default to the split view controller and change self.preferredDisplayMode in your splitview and coming to moving the category buttom u either can use the right bar button in navigationbar or create your custom navigation bar.
Hope this helps
For those who are having the same issue, I found a very simple solution. All you need to do is assign the rightBarButtonItems with leftBarButtonItems value and set the leftBarButtonItems to nil. Voila, that's about it.
if let leftButton = self.navigationItem.leftBarButtonItems {
self.navigationItem.rightBarButtonItems = leftButton
self.navigationItem.leftBarButtonItems = nil
}

Popping consecutive view controllers and returning to main view controller (using navigation controller)

I'm following the Firebase-Chat-Messenger example in the "let's build that app" Youtube videos, and it works fine.
However, I'm testing integration inside a test application :
My test app has a menu with buttons and one of them is for the chat, which takes us to a similar interface (login menu and so on, anything beyond it is similar to the example in the tutorial. But you don't need to check it to answer my question).
Main menu button => Login/Register interface => Chat interface
I can't find a way to dismiss the chat interface to return to the main menu of the app, dismiss always returns to the login/register interface and sometimes causes errors. Could you suggest a good solution to use for this?
tl;dr : How to dismiss two or more views and return to main view (main menu) of app?
P.S : I'm new to Swift and still struggling with some basic elements, Sorry if the question seems too simple.
Use either popToRootViewController(animated:) to pop to the root view controller, or popToViewController(_:animated:) and provide the spicific controller you'd like to pop to.

Prevent views stealing focus/setting focus to a view

I have an MFC sdi app that uses a splitter window to contain a tree control alongside the main view showing the data.
When the user selects something in the tree, that view keeps focus until the user deliberately clicks in the main data window. This means that any toolbar buttons associated with the main view are disabled.
Is there any way to programmatically switch focus back to the main view after the user has clicked the tree control? Or am I doing something fundamentally wrong using a CSplitterWnd and 2 views?
You don't want to bring the focus back to the other view as soon as someone clicks the tree: It would make your app unusable. e.g. It would prevent users from navigating through the tree using the keyboard since the tree would never keep the focus long enough.
I you really want the toolbar to keep reflecting the state of your 2nd view (I'm not sure it's a good idea), you have a few options. Make your pick. 2 come to mind:
Your tree view should NOT be a CView. Use a simple CTreeCtrl. Not very nice because it kind of break the doc/view paradigm (e.g. no more tree's OnUpdate() called whenever an UpdateAllViews() is called).
Prevent the tree from becoming the active view. To do so:
2.a. When you view gets the focus (OnSetFocus()):
STATIC_DOWNCAST(CFrameWnd, AfxGetMainWnd())->SetActiveView(pTheOtherView);
2.b. Derive a CMySplitterWnd class from CSplitterWnd, then override CMySplitterWnd::SetActivePane() to prevent it from setting the treeview as the active view.
In all cases, welcome to the wonderful world of MFC internals where diving into the source code is the mandatory daily sport ;-)