Jetpack navigation compose, bottom nav, make back button switch tabs? - android-jetpack-compose

I'm trying to use bottom navigation (ie, tabs) with Android Jetpack Compose and the Navigation Compose library. I have it set up with multiple back stacks, so that the state of each tab is preserved when you switch between them. However, if I change tabs by tapping one of them, the Android back button does not go back to the previous tab. Instead it navigates within that tab. How do I set it up to go back to previous tab?
Example scenario (I want to change behavior of last step).
I have two tabs, A and B.
Start in the A tab, on screen A1.
Push a new screen in that tab, called A2.
Tap the B tab to move to it, on its start screen B1.
Push a new screen in that tab, B2. So the tab stacks are now: A:[A1,A2], and B:[B1, B2]
Tap the A tab. I'm back in that stack, on screen A2. The state in that tab was preserved.
Press Android back button. It goes to A1. Instead I want it to go back to the B tab, screen B2.
MyAppBottomNavItem.all.forEach { item ->
BottomNavigationItem(
icon = { Icon(item.icon, contentDescription = null) },
label = {
Text(item.name, maxLines = 1, textAlign = TextAlign.Center,
overflow = TextOverflow.Visible, softWrap = false,
fontSize = 10.sp)
},
selected = currentDestination?.hierarchy?.any { it.route == item.route } == true,
alwaysShowLabel = true,
onClick = {
nav.navigate(item.route) {
popUpTo(nav.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}

Related

Toggle and untoggle a DropdownMenu's appearance

I have an Icon . And when the Icon is clicked it toggles the expanded state variable. The expanded state variable toggles a DropdownMenu. And that DropdownMenu appears underneath the Icon.
DropdownMenu has a onDismissRequest callback. onDismissRequest runs when the user clicks outside the DropdownMenu. onDismissRequest toggles the expanded state variable, and so closes the DropdownMenu.
However, if the user clicks outside DropdownMenu, and specifically on the icon, onDismissRequest sets expanded to false. But the user has also clicked on the Icon. And the Icon sets expanded to true.
And so, clicking on the icon again does not close the DropdownMenu: it opens it.
#Composable
fun MyComponent() {
var expanded by remember { mutableStateOf(false) }
Column() {
Icon(Icons.Filled.Menu, "",
Modifier.clickable { expanded = !expanded }
)
DropdownMenu(expanded, { expanded = false }) {
DropdownMenuItem({ }) {
Text("Menu item")
}
}
}
}
So, how can I toggle and untoggle a DropdownMenu's appearance?
If I could make onDismissRequest swallow all the interactions I could prevent my Icon's click listener opening the menu again--but I'm not sure that's possible.
You can disable clickable when it's not expanded:
.clickable(enabled = !expand)
Make the clicking on the icon only opening the dropdown menu, instead of toggling it:
Icon(Icons.Filled.Menu, "",
Modifier.clickable { expand = true }
)
Also, make clicking on any of the dropdown menu items to close the menu:
DropdownMenuItem(onClick = { expand = false})
That way, clicking the icon will only expand the dropdown, and clicking on any dropdown item or anywhere else will close it.

ToolbarItems do not look right in iOS

I have a Xamarin.Forms app with FreshMvvm, and am trying to use secondary ToolbarItems. Here is a part of my PageModel code:
public override void Init(object initData)
{
CurrentPage.ToolbarItems.Add(new ToolbarItem() { Text = "About LATICRETE", Command = AboutCommand, Priority = 0, Order = ToolbarItemOrder.Secondary });
CurrentPage.ToolbarItems.Add(new ToolbarItem() { Text = "Call LATICRETE", Command = CallCommand, Priority = 0, Order = ToolbarItemOrder.Secondary });
CurrentPage.ToolbarItems.Add(new ToolbarItem() { Text = "Email Technical Support", Command = EmailTechSupportCommand, Priority = 0, Order = ToolbarItemOrder.Secondary });
CurrentPage.ToolbarItems.Add(new ToolbarItem() { Text = "Visit LATICRETE Website", Command = VisitWebsiteCommand, Priority = 0, Order = ToolbarItemOrder.Secondary });
For Android, after pressing the hamburger button, the menu looks like I expect:
But at iPhone, it is quite different:
As you can see, there is no hamburger button, and all the ToolbarItems are placed horizontally next to each other, and as they do not fit withing the width of the screen, they overlap. I realize that this is the normal behavior for iOS, and yet it is not acceptable for me. Is there any way to fix it?
On iOS, the Secondary items menu appears below the navigation bar as a horizontal list.
if you want to acheve the effect like in Android,you could create a custom PageRenderer.
here is a sample,you could refer to it iOSSecondaryToolbarMenubar
the effect in Android :
the effect in ios (you could change the icon in your renderer):
1) the first page has the toolbar items:
2) all pages have the toolbar items:

Prevent click through view in swift

I'm working in Xcode and swift, I created a view acting as a menu that toggles on tap, when the menu comes out I can still click a test button underneath it. I don't want that to happen. I want everything behind the view to be disabled giving priority to the menu view. (View Image below)
screenshot from the sample app
Keep in mind that I'm not considering one button, if that was the case I would've disabled that specific button. This page will be a scroll view and it will be dynamic.
this is the code that I'm using:
#IBAction func MenuButton(sender: UIButton) {
if self.MenuView.frame.origin.x == -180 {
UIView.animateWithDuration(0.5, animations:{
self.MenuView.frame = CGRectMake(self.MenuView.frame.origin.x + 180, self.MenuView.frame.origin.y, self.MenuView.frame.size.width, self.MenuView.frame.size.height)
})
} else {
UIView.animateWithDuration(0.5, animations:{
self.MenuView.frame = CGRectMake(self.MenuView.frame.origin.x - 180, self.MenuView.frame.origin.y, self.MenuView.frame.size.width, self.MenuView.frame.size.height)
})
}
}
the view is hidden 180 pixels on the left side, when the menu button is clicked the view will animate 180 pixels to the right which brings it to the front. The function checks if the view is already opened so it can animate it back 180 pixel to hide it.
The only thing I need is to disable clicking through the view.
Swift 3 version that worked great for me in stopping the click through (thanks to the previous comment by #Ismail).
myAddedSubView.isUserInteractionEnabled = true
This is the 'simple, one-line' answer and works like z index (presuming you wanted the z index to be 'absolute top'.
The fact that the button is still visible and clickable means that it must be in front of the menu. If you rearrange the order of things so that the menu is in front of the button, then you should get the result that you are looking for.

Xamarin UITabbar multi bar items

I am using Xamarin Studio 6.0
I have created a TabBar and have added multi items to it, the items cover each others.
This is the code and screenshot:
var items = new UITabBarItem[10];
for (int i = 0; i < 10; i++)
{
var tabBarItem = new UITabBarItem("TAB ITEM"+i, null, i);
items[i] = tabBarItem;
}
TabLanguageBar.Items = items;
TabLanguageBar.ItemSpacing = 10;
TabLanguageBar.ItemSelected += (sender, e) =>
{
Console.WriteLine("tab bar button item slected");
};
That is the way a UITabBar works, you will need to either display a subset of them at one time or alter your UI design.
A tab bar displays all of its tabs onscreen at once, using the itemPositioning property to determine how to position items in the available space.
If you have more items than can fit in the available space, display only a subset of them and let the user select which tabs are displayed. The beginCustomizingItems: method displays an interface for selecting which tab bar items to display.
Ref: UITabBar

Xamarin IOS Change color of button momentarily

I'm creating a quiz application. The user selects an answer, get a brief confirmation whether the answer is correct or wrong before automatically is directed to the next question.
So, I have a view that has a label and 4 different buttons with different texts coming from database. When the user selects a button, it should flash or have a different background color for few seconds before the buttons are loaded with different text.
I have tried doing this in the touchUpInside. I set a different color for the button and I do Thread.Sleep(2000). This is my event handler of the TouchUpInside of one of the buttons:
partial void Answer(MonoTouch.Foundation.NSObject sender)
{
// if wrong answer, highlight to red and move on.
((UIButton)sender).backgroundColor = UIColor.Red;
Sleep(2000); // freeze to display the red color for 2 seconds
LoadNextQuestion(); // load the next question method
}
But the color only changes after the next question loads. How can I make it freeze there for 2 seconds?
thanks
You can do this with an animation:
button1.TouchDown += delegate(object sender, EventArgs e) {
UIView.Animate(2,0,UIViewAnimationOptions.Autoreverse,
() => { button2.BackgroundColor = UIColor.Yellow; },
() => { button2.BackgroundColor = UIColor.Green; });
};
Here button1 is triggering the animation of button2, but you could setup the trigger to be anything. This sample just animates the button's background color from Green to Yellow and back Again, with a 2s duration.

Resources