Jetpack Compose AnimatedNavHost Close issue - android-jetpack-compose

I am trying to replace the NavHost with AnimatedNavHost, but having an issue.
Using NavHost I have this structure:
#Composable
fun AppNavHost(...){
val navController = rememberNavController()
NavHost(navController = navController, ...) {
composable("1") { Screen1() }
composable("2") { Feature1NavHost() }
}
}
In Feature1NavHost, I have another NavHost that takes control of the feature navigation. So, Screen-1 calls “2” and pops out of the stack. Everything works fine here.
Using AnimatedNavHost, when I press back in the first screen of Feature1NavHost, the display blinks and the application does not close. I have to press a lot to close the app.

Related

How to get initial focus in compose

How to get initial keyboard focus on an Android compose app?
My view looks like
Parent { Child { Button} }
I tried implementing it in the Parent composable function....
FocusRequester is not initialized. Here are some possible fixes:
1. Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
2. Did you forget to add a Modifier.focusRequester() ?
3. Are you attempting to request focus during composition? Focus requests should be made in response to some event. Eg Modifier.clickable { focusRequester.requestFocus() }
The following code woirks like a charm....
fun Modifier.requestInitialFocus() = composed {
val first = remember { FocusRequester() }
LaunchedEffect(first) {
delay(1)
first.requestFocus()
}
focusRequester(first)
}
Original:
This error does not happen when implementing it in the composable function, where the target element is a direct child....
So implementing it in the Child seems to be a solution....

Is there any way to override the back stack button to go back to a screen with its index in jetpack compose?

Is there any way to override onBackPress to go back to a screen with its index in jetpack compose? For example, go back to the second previous screen.
You can with backhandler function;
BackHandler(
enabled = //condition if you want.
) {
// Navigate where ever you want.
//Example;
navController.navigate(
route = navController.backQueue[i].destination.route.toString()
)
}
You can use Custom BackHandler in this case.
BackHandler(
enabled = true,
onBack = {navController.navigate(route)}
)

Jetpack Compose navigation: login screen and different screen with bottom navigation

My goal is to to have a LoginScreen from which I can navigate to an InternalScreen. The InternalScreen should have/be a bottom navigation bar that can navigate to multiple other screens/routes in the internal space.
This is what I imagined my NavGraph was supposed to look like:
- LoginScreen
- internal space
- InternalScreen with BottomNavigation
- some fragment
- some other fragment
My idea was to create a Scaffold with a BottomNavigationBar in the InternalScreen composable but I do not no where to put it in my NavGraph since said NavGraph also has to contain the different routes for the BottomNavigationBar.
How should I approach this? I am sorry if this has already been answered, I couldn't find anything about this particular case.
I think the login screen/flow must be part of the application navigation flow. In summary, your application must react to a isLoggedIn state, which should be global, and in case of the user is not logged in, the login screen must be displayed.
This is what I did:
#Composable
fun MainNavigation(
viewModel: MainViewModel,
navController: NavHostController,
) {
val auth = viewModel.auth
val initialRoute =
if (auth.isLoggedIn()) BooksFeature.route else LoginFeature.route
AnimatedNavHost(
navController,
startDestination = initialRoute
) {
loginGraph(auth, navController)
booksGraph(auth, navController)
settingsGraph(navController)
}
}
The MainNavigation composable is the root of my app (which is called in setContent at MainActivity). Each feature of the app has a navigation graph. Like booksGraph:
fun NavGraphBuilder.booksGraph(
auth: Auth, // this is a simple class which
// knows if the user is logged in
navController: NavHostController
) {
navigation(
route = BooksFeature.route,
startDestination = BooksList.route,
) {
composable("ScreenA") {
ScreenA()
}
...
}
}
In my activity (I'm using just one activity), I'm observing the login state and redirecting to the login screen properly.
private fun launchLoginObserver() {
lifecycleScope.launch(Dispatchers.Main) {
mainViewModel.isLoggedIn.collect { isLoggedInState ->
if (isLoggedInState == false) {
navigationController.navigate(LoginScreen.route) {
popUpTo(0) // reset stack
}
}
}
}
}
If you want to take a look into the full implementation, here is the link for my repository.

Monotouch back to first ViewController

I'm having a problem going back again to my first Apps VC, the first "screen/ViewController)" is a login screen, then I call a UITabbar with their respective ViewControllers, when I'm on a certain level of a ViewController (for example the 5th one) I want to get a "Logout" behavior in my App and get back to the first ViewController (Login). But I think I can only Navigate back to the first ViewController of my Tabbar control. I was trying with this methods of my VC:
this.NavigationController.PopToViewController(previousVC,true);
or
this.NavigationController.PopToRootViewController(true);
Any help would be appreciated.
(If you need more details with the code please tell me about it)
//Call to the tab bar from the login viewcontroller
mainTBC = new TabBarMenuPpal ();
this.NavigationController.PushViewController (mainTBC, true);
…
//Tabbarmenuppal with a set of navcontrollers
public TabBarMenuPpal ()
{
var customerVC = new Customers ();
navCustomers = new UINavigationController ();
navCustomers.PushViewController (customerVC, true);
navCustomers.TopViewController.Title = customersTitle;
navCustomers.TabBarItem = new UITabBarItem (customersTitle, UIImage.FromFile ("Utility/Images/Cust-30x30.png"), 0);
…
mainVC = new UIViewController[]
{
navCustomers
, navSettings
} ;
this.ViewControllers = mainVC;
}
The problem is that when I start to navigate in the navCustomers I can't find a way to go back to the login VC (deleting my tab bar and releasing all their resources). (Sorry about my English).
I don't know if it's the best solution but I have implemented a "GoToLogin" method in my UITabBarController which only does this:
public void GoToLogin()
{
this.NavigationController.PopToRootViewController(true);
}
So when I need to go to my first page I only do this:
if(MainDialog.NavigationController.TabBarController != null)//loaded from the tab bar
((TabBarMenuPpal)MainDialog.NavigationController.TabBarController).GoToLogin();
else//loaded from the login screen
MainDialog.NavigationController.PopToRootViewController(true);

Custom Back Button in NavigationGroup (Titanium Mobile)

Developing in Titanium Mobile (latest SDK)
I have a navigationGroup with navBarHidden set to true. Within my windows, I have custom Back and Next buttons. The next button is obviously a cake walk, as it just opens a new window within the navigation group.
My question is the back button. How can I give my back button the same functionality as the default back button which iOS automatically adds to a navigationGroup?
Why you are hiding your navbar?
you declare a navigation group like this:
var nav = Titanium.UI.iPhone.createNavigationGroup({
window: win1 //win1 is window defined above
});
Now suppose you have win2(another window) on which you navigate.
so while opening that win2 just do like this
nav.open(win2,{animated:true});
by doing this the titanium will automatically add a back button on the top.
OR
you can do like this if you dont want that automatic back button
var win = Titanium.UI.currentWindow;
var b = Titanium.UI.createButton({title:'Back'});
win.leftNavButton = b;
b.addEventListener('click', function()
{
alert('I was clicked'); // to confirm its being called
// do the stuff here
win.close();
});

Resources