Push Front View up with Keyboard, don't push Background View up in Kotlin Compose - kotlin

I want to do something like this:
Where there is a view that pops on top of the open keyboard.
I've tried to do this, and I have this so far:
However, when I put this view in a Box, as the second view, the first view is also pushed up, here's the code:
#OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class)
#ExperimentalComposeUiApi
fun Modifier.bringIntoViewAfterImeAnimation(): Modifier = composed {
var focusState by remember { mutableStateOf<FocusState?>(null) }
val relocationRequester = remember { BringIntoViewRequester() }
val isImeVisible = WindowInsets.isImeVisible
LaunchedEffect(
isImeVisible,
focusState,
relocationRequester
) {
if (isImeVisible && focusState?.isFocused == false) {
relocationRequester.bringIntoView()
}
relocationRequester.bringIntoView()
}
bringIntoViewRequester(relocationRequester).onFocusChanged { focusState = it }
}
#OptIn(ExperimentalComposeUiApi::class)
#Composable
fun SpaceCreator(navController: NavController) {
Column(
modifier = Modifier.fillMaxSize().clip(RoundedCornerShape(10.dp)),
verticalArrangement = Arrangement.Bottom
) {
SpaceCreatorContainer()
}
}
#OptIn(ExperimentalComposeUiApi::class)
#Composable
fun SpaceCreatorContainer() {
Card(
modifier = Modifier
.bringIntoViewAfterImeAnimation()
.shadow(elevation = 10.dp, shape = RoundedCornerShape(10.dp), clip = true)
.background(color = colors.background)
) {
SpaceCreatorWrapper()
}
}
#Composable
fun SpaceCreatorWrapper() {
val localFocusManager = LocalFocusManager.current
Column(
modifier = Modifier.padding(15.dp).clip(RoundedCornerShape(10.dp))
) {
Text(
modifier = Modifier.fillMaxWidth(),
text = "Top Text"
)
Text(text = "Content")
OutlinedTextField(
value = "ss",
onValueChange = { },
label = { Text("Email Address") },
singleLine = true,
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(
onDone = { localFocusManager.clearFocus() }
)
)
OutlinedTextField(
value = "ss",
onValueChange = { },
label = { Text("Email Address") },
singleLine = true,
modifier = Modifier.fillMaxWidth(),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = { localFocusManager.clearFocus() }
)
)
Text(text = "Content")
}
}
That's the code for SpaceCreator(), and then I add it to a Box where it's supposed to float over another view, like so:
BoxWithConstraints(
propagateMinConstraints = true
) {
Box(
modifier = Modifier
.fillMaxSize()
) {
MainView()
SpaceCreator(navController = navController)
}
}
How do I only push up the second view in the Box when the keyboard is opened, and not the entire box?
Also,
Currently, I have a AnimationNavigation screen which is a Box(fillMaxSize), and the content of the keyboard modal stuck to the bottom. I also have a auto focus on the input, which is making the navigation a bit slow, unlike other apps I've seen.
Is there a smooth way to do this on low-mid-range devices like Samsung A23?
Thank you.

Related

Jetpack Compose: How to show Alert Dialog with a single item's information from LazyColumn clicked item?

I'm working on a simple project where I import a database of inventory items with room and can modify inventory according to changes. I'm struggling with the LazyColumn.
What I need: When an item from LazyColumn is clicked, show alert dialog with item info.
What happens: When an item from LazyColumn is clicked, it shows all the items alert dialog (generates 100+ alert dialogs and only the last one is visible).
Application Main page with LazyColumn:
After clicking on item shows huge shadow of 100+ Alert dialogs and only the last item is visible:
//custom alert dialog taking parameters from the database class of the inventory items
#Composable
fun ItemAlertDialog(
onDismiss: () -> Unit,
onNegativeClick: () -> Unit,
onPositiveClick: () -> Unit,
currentInventory: Int,
itemDescription: String,
itemNumber: String,
) {
var incoming by remember { mutableStateOf(0f) }
var outgoing by remember { mutableStateOf(0f) }
Dialog(onDismissRequest = onDismiss) {
Card(
elevation = 8.dp,
shape = RoundedCornerShape(12.dp)
) {
Column(modifier = Modifier.padding(8.dp)) {
Text(
text = itemNumber,
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
modifier = Modifier.padding(8.dp)
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = itemDescription,
fontWeight = FontWeight.Normal,
fontSize = 15.sp,
modifier = Modifier.padding(8.dp)
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = currentInventory.toString(),
fontWeight = FontWeight.ExtraBold,
color = Color(0xFF0FFC107),
fontSize = 20.sp,
modifier = Modifier.padding(8.dp)
)
// Update Inventory
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Column {
Text(text = "Incoming ${incoming.toInt()}")
Slider(
value = incoming,
onValueChange = { incoming = it },
valueRange = 0f..100f,
onValueChangeFinished = {}
)
Spacer(modifier = Modifier.height(8.dp))
Text(text = "Outgoing ${outgoing.toInt()}")
Slider(
value = outgoing,
onValueChange = { outgoing = it },
valueRange = 0f..100f,
onValueChangeFinished = {}
)
}
}
// Buttons
Row(
horizontalArrangement = Arrangement.End,
modifier = Modifier.fillMaxWidth()
) {
TextButton(onClick = onNegativeClick) {
Text(text = "CANCEL")
}
Spacer(modifier = Modifier.width(4.dp))
TextButton(onClick = {
onPositiveClick.invoke()
}) {
Text(text = "OK")
}
}
}
}
}
}
Items row code with the onclick I want to fire the dialog with:
#Composable
fun MainScreenItemRow(
itemNumber: String,
itemDescription: String,
currentInventory: Int,
onclick: () -> Unit
) {
Row(modifier = Modifier
.clickable {
onclick.invoke()
}
.border(width = 1.dp, color = Color.Gray, shape = RoundedCornerShape(8.dp))
.padding(16.dp)
.clip(shape = RoundedCornerShape(8.dp)),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = itemNumber,
fontSize = 12.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.weight(3f)
)
Spacer(modifier = Modifier.width(10.dp))
Text(
text = itemDescription,
fontSize = 12.sp,
maxLines = 3,
modifier = Modifier.weight(4f)
)
Spacer(modifier = Modifier.width(30.dp))
Text(
text = currentInventory.toString(),
fontSize = 20.sp,
color = Color(0xFF0FFC107),
modifier = Modifier.weight(1f)
)
}
}
MainActivity code (apologies for messy code, notes annotated with //***):
#AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val mainViewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val systemUiController = rememberSystemUiController()
val useDarkIcons = MaterialTheme.colors.isLight
val inventoryList by mainViewModel.getInventoryItems.collectAsState(initial = emptyList())
val showItemDialog = remember { mutableStateOf(false)}
val result = remember { mutableStateOf("") }
val expanded = remember { mutableStateOf(false) }
val randomList = listOf("")
val selectedItem = remember{ mutableStateOf(randomList[0])}
//*** getting inventoryList from the flow, added remember to selectedItem and showItemDialog
SimpleInventoryTheme {
ItemModelDrawer{drawerState, drawerScopeState ->
SideEffect {
systemUiController.setSystemBarsColor(
color = Color.Transparent,
darkIcons = useDarkIcons
)
}
Scaffold(
topBar = {
TopAppBar(
title = {
Text(text = "Inventory Manager")
},
actions = {
IconButton(onClick = {
drawerScopeState.launch {
drawerState.open()
}
}) {
Icon(Icons.Outlined.Search, contentDescription = "Search")
}
Box(
Modifier
.wrapContentSize(Alignment.TopEnd)
) {
IconButton(onClick = {
expanded.value = true
result.value = "More icon clicked"
}) {
Icon(
Icons.Filled.MoreVert,
contentDescription = "Localized description"
)
}
DropdownMenu(
expanded = expanded.value,
onDismissRequest = { expanded.value = false },
) {
DropdownMenuItem(onClick = {
expanded.value = false
result.value = "First item clicked"
}) {
Text("First Item")
}
Divider()
DropdownMenuItem(onClick = {
expanded.value = false
result.value = "Second item clicked"
}) {
Text("Second item")
}
}
}
},
backgroundColor = Color.White,
elevation = AppBarDefaults.TopAppBarElevation
)
},
content = {
Column(modifier = Modifier.fillMaxSize()) {
MainScreenTitlesRow()
Divider()
//*** Showing the items in the main page and adding onclick to fire up the alert dialog
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
itemsIndexed(inventoryList) { idx, item ->
item.currentInventory?.let {
MainScreenItemRow(
itemNumber = item.itemNumber,
itemDescription = item.itemDescription,
currentInventory = it,
onclick = {
//*** trying to set the clicked item into "selectedItem" val
selectedItem.value = item.itemNumber
selectedItem.value = item.itemDescription
selectedItem.value = item.currentInventory.toString()
Log.d("MainActivityItemClicked", "$selectedItem ")
showItemDialog.value = true
}
)
}
}
}
//*** Trying to check which item was clicked and only present its information in the alert dialog but it loads up all the items
if (showItemDialog.value) {
LazyColumn {
itemsIndexed(inventoryList) { _, item ->
item.currentInventory?.let {
ItemAlertDialog(
itemNumber = item.itemNumber,
itemDescription = item.itemDescription,
currentInventory = it,
onDismiss = {
showItemDialog.value = !showItemDialog.value
Toast.makeText(
this#MainActivity,
"Dialog dismissed!",
Toast.LENGTH_SHORT
)
.show()
},
onNegativeClick = {
showItemDialog.value = !showItemDialog.value
Toast.makeText(
this#MainActivity,
"Cancel!",
Toast.LENGTH_SHORT
)
.show()
},
onPositiveClick = {
showItemDialog.value = !showItemDialog.value
Toast.makeText(
this#MainActivity,
"Saved!",
Toast.LENGTH_SHORT
)
.show()
}
)
}
}
}
}
}
}
)
}
}
}
}
}
Thank you #Philip Dukhov
I've tried doing this previously and couldn't get the item.Number, item.description, item.inventory at all (val not resolved) so used the inventoryList since I could get it at least smething which was the wrong approach per your suggestion.
I learned a thing or two in the last few days struggling, so with your tip I managed to achive what I need. Not sure it's the right way but it works now. On to the next struggle!
//***Modified the selected Item from val selectedItem = remember{ mutableStateOf(randomList[0])} to separate 3:
val selectedItemNumber = remember{ mutableStateOf(randomList[0])}
val selectedItemDescription = remember{ mutableStateOf(randomList[0])}
val selectedItemInventory = remember{ mutableStateOf(randomList[0])}
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
itemsIndexed(inventoryList) { idx, item ->
item.currentInventory?.let {
MainScreenItemRow(
itemNumber = item.itemNumber,
itemDescription = item.itemDescription,
currentInventory = it,
onclick = {
selectedItemNumber.value = item.itemNumber
selectedItemDescription.value = item.itemDescription
selectedItemInventory.value = item.currentInventory.toString()
Log.d("MainActivityItemClicked", "$selectedItemDescription ")
showItemDialog.value = true
}
)
}
}
}
if (showItemDialog.value) {
ItemAlertDialog(
itemNumber = selectedItemNumber.value,
itemDescription = selectedItemDescription.value,
currentInventory = selectedItemInventory.value.toInt(),
onDismiss = {
showItemDialog.value = !showItemDialog.value
Toast.makeText(
this#MainActivity,
"Dialog dismissed!",
Toast.LENGTH_SHORT
)
.show()
},
onNegativeClick = {
showItemDialog.value = !showItemDialog.value
Toast.makeText(
this#MainActivity,
"Cancel!",
Toast.LENGTH_SHORT
)
.show()
},
onPositiveClick = {
showItemDialog.value = !showItemDialog.value
Toast.makeText(
this#MainActivity,
"Saved!",
Toast.LENGTH_SHORT
)
.show()
}
)
}
}

Clickable Toggle Continuously Repeating Causing UI Glitch in Search Bar - Jetpack Compose Android Studio Kotlin

I'm trying to have the text field appear when the "Search Movies" button is selected, and disappear when not selected.
When I tap on the "Search Movies" button, the app seems to recognize the clicks constantly.
Here's a video of what it looks like: https://youtu.be/5LQ8k0Y05Cc
As you can see, the text field also doesn't disappear when the "Popular Movies" button is selected.
Here's the composable function:
#Composable
fun MaterialButtonToggleGroup() {
val options = listOf(
"Popular Movies",
"Search Movies"
)
var selectedOption by remember {
mutableStateOf("")
}
val onSelectionChange = { text: String ->
selectedOption = text
}
Column() {
var isExpanded by remember { mutableStateOf(false) }
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
modifier = Modifier.fillMaxWidth(),
) {
options.forEach { text ->
Row(
modifier = Modifier
.padding(
vertical = 8.dp,
),
) {
Text(
text = text,
style = typography.body1.merge(),
color = Color.White,
modifier = Modifier
.clip(
shape = RoundedCornerShape(
size = 12.dp,
),
)
.clickable {
onSelectionChange(text)
}
.background(
if (text == selectedOption) {
Color.Magenta
} else {
Color.Gray
}
)
.padding(
vertical = 12.dp,
horizontal = 16.dp,
),
)
}
}
}
if (selectedOption == "Search Movies") {
isExpanded = !isExpanded
}
if (isExpanded) {
var text by remember { mutableStateOf("") }
OutlinedTextField(
value = text,
modifier = Modifier.fillMaxWidth()
.padding(all = 3.dp),
onValueChange = { text = it },
label = { Text("Enter Movie Info") }
)
}
}
(activity as MainActivity?)?.viewSelection(selectedOption)
}
Surface {
MaterialButtonToggleGroup()
}
Turns out I should just set isExpanded to true or false for each scenario.
I changed:
if (selectedOption == "Search Movies") {
isExpanded = !isExpanded
}
if (isExpanded) {
var text by remember { mutableStateOf("") }
OutlinedTextField(
value = text,
modifier = Modifier.fillMaxWidth()
.padding(all = 3.dp),
onValueChange = { text = it },
label = { Text("Enter Movie Info") }
)
}
To:
if (selectedOption == "Search Movies") {
isExpanded = true
} else {
isExpanded = false
}
if (isExpanded) {
var text by remember { mutableStateOf("") }
OutlinedTextField(
value = text,
modifier = Modifier
.fillMaxWidth()
.padding(all = 3.dp),
onValueChange = { text = it },
label = { Text("Enter Movie Info") }
)
}

Jetpack Compose - Disable TextField long press handler

I have an IconButton in the trailingIcon of OutlinedTextField like:
OutlinedTextField(
modifier = Modifier.weight(1f),
label = { Text(text = "Label") },
value = text,
onValueChange = { text = it },
trailingIcon = {
IconButton2(onClick = {
println("onClick")
}, onLongClick = {
println("onLongClick shows TextToolbar")
}) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = null
)
}
}
)
IconButton2 is just a copy of IconButton but with combinedClickable to include onLongClick instead of clickable.
The problem is that when I long click IconButton2, it shows the TextToolbar for the TextField. Doesn't matter what I do, the text field will handle long click, show the TextToolbar and provide haptic feedback.
Even if I use pointerInput with awaitPointerEvent and consumeAllChanges (like here) it still triggers it. The TextField doesn't answer to any tap or anything but if I long click it, it answers!
The workaround I'm doing for now is wrapping the text field in a Row and add the IconButton beside it instead of "inside" but I needed to have the icon button as the trailingIcon.
Is there any way to properly do it?
Compose 1.0.3 and 1.1.0-alpha05 both behaves the same.
I ended up making a small hack that seems to be working fine, so basically I add a dummy Box as the trailingIcon to get the position of it, then I add an IconButton outside of it (both wrapped in a Box) and I also get the position of it + I offset it using the position of the dummy box. Not the ideal solution but works fine.
Here's the full source if anyone needs it:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
Surface(
modifier = Modifier.padding(16.dp),
color = MaterialTheme.colors.background
) {
var text by remember { mutableStateOf("") }
var trailingIconOffset by remember { mutableStateOf(Offset.Zero) }
var iconButtonOffset by remember { mutableStateOf(Offset.Zero) }
val colors = TextFieldDefaults.outlinedTextFieldColors()
Column {
//With hack
Box {
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
label = { Text(text = "With hack") },
value = text,
onValueChange = { text = it },
trailingIcon = {
Box(modifier = IconButtonSizeModifier
.onGloballyPositioned {
trailingIconOffset = it.positionInRoot()
}
)
},
colors = colors
)
val contentColor by colors.trailingIconColor(
enabled = true,
isError = false
)
CompositionLocalProvider(
LocalContentColor provides contentColor,
LocalContentAlpha provides contentColor.alpha
) {
IconButton2(
modifier = Modifier
.onGloballyPositioned {
iconButtonOffset = it.positionInRoot()
}
.absoluteOffset {
IntOffset(
(trailingIconOffset.x - iconButtonOffset.x).toInt(),
(trailingIconOffset.y - iconButtonOffset.y).toInt()
)
},
onClick = {
text = "onClick"
},
onLongClick = {
text = "onLongClick"
}
) {
Icon(imageVector = Icons.Filled.Menu, contentDescription = null)
}
}
}
//Without hack
Box {
OutlinedTextField(
modifier = Modifier.fillMaxWidth(),
label = { Text(text = "Without hack") },
value = text,
onValueChange = { text = it },
trailingIcon = {
IconButton2(
onClick = {
text = "onClick"
},
onLongClick = {
text = "onLongClick"
}
) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = null
)
}
},
colors = colors
)
}
}
}
}
}
}
}
private val RippleRadius = 24.dp
private val IconButtonSizeModifier = Modifier.size(48.dp)
#OptIn(ExperimentalFoundationApi::class)
#Composable
fun IconButton2(
modifier: Modifier = Modifier,
onClick: () -> Unit,
onLongClick: (() -> Unit)? = null,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: #Composable () -> Unit
) {
Box(
modifier = modifier
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
enabled = enabled,
role = Role.Button,
interactionSource = interactionSource,
indication = rememberRipple(bounded = false, radius = RippleRadius)
)
.then(IconButtonSizeModifier),
contentAlignment = Alignment.Center
) {
val contentAlpha = if (enabled) LocalContentAlpha.current else ContentAlpha.disabled
CompositionLocalProvider(LocalContentAlpha provides contentAlpha, content = content)
}
}

How to move DropdownMenu to preferable location in Jepack Compose

Is it possible to center DropdownMenu in my example? or show it wherever I click or tap?
I tried alignment and arrangements and none of them work. I prefer showing the DropdownMenu wherever I tab but I couldn't find a way to do it.
fun main() = Window {
var helloText by remember { mutableStateOf("") }
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Item("Darian", "Russ") {
helloText = it
}
Item("Maynerd", "Andre") {
helloText = it
}
Item("Sandra", "Victoria") {
helloText = it
}
Spacer(modifier = Modifier.height(2.dp))
Text(text = helloText)
}
}
#Composable
fun Item(text: String, text2: String, onMenuTab: (String) -> Unit) {
var expanded by remember { mutableStateOf(false) }
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
val modifier = Modifier.clickable {
expanded = true
}
DropdownMenu(
expanded = expanded,
onDismissRequest = {
expanded = false
}
) {
DropdownMenuItem(onClick = {
onMenuTab("hello $text $text2")
expanded = false
}, modifier = Modifier.align(Alignment.CenterHorizontally)) {
Text("Hello")
}
DropdownMenuItem(onClick = { /* Handle settings! */ }) {
Text("Settings")
}
Divider()
DropdownMenuItem(onClick = { /* Handle send feedback! */ }) {
Text("Send Feedback")
}
}
Text(text = text, modifier = modifier)
Text(text = text2, modifier = modifier)
Divider(modifier = Modifier.height(2.dp))
Spacer(modifier = Modifier.height(2.dp))
}
}
For me fixing the alignment of the popup did the trick-
Popup(alignment = Alignment.TopStart)
Earlier it was Popup(alignment = Alignment.CenterStart)
and that was taking my popup view to the top of the screen. But now comes below the clicked item.

Navigation in Jetpack Compose

I am working on this shopping app which uses radio buttons. The customer should be able to select a radio button and go it by clicking the 'select button'.
Can anyone help me get get started.
the code is below.
I hope this makes sense to everyone. I have made a page for each of the radio buttons. pages are name the same as the buttons.
#Composable
fun MyRadioGroup() {
val navController = rememberNavController()
val radioOptions = listOf(
"Dollar Store", "Fred Myers",
"Wall Mart", "SafeWay", "Sherm's", "CostCo", "Other"
)
val (selectedOption, onOptionSelected) = remember {
mutableStateOf(radioOptions[1])
}
Scaffold() {
TopAppBar(
title = { Text(stringResource(id = R.string.app_name)) },
)
}
Column(
modifier = Modifier
.padding(start = 16.dp, top = 160.dp)
) {
Text(
text = "Select Store from List Below")
Divider()
Text(
text = "Then push the 'Select'")
}
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
radioOptions.forEach { text ->
Row(
Modifier
.fillMaxWidth()
.padding(top = 8.dp)
.selectable(
selected = (text == selectedOption),
onClick = { onOptionSelected(text) }
)
.padding(horizontal = 16.dp)
) {
RadioButton(
selected = (text == selectedOption),
modifier = Modifier
.padding(start = 16.dp, top = 12.dp),
onClick = {
onOptionSelected(text)
}
)
Text(
text = text,
modifier = Modifier.padding(start = 16.dp, top = 16.dp)
)
}
}
}
Column(modifier = Modifier
.padding(start = 24.dp, top = 640.dp)
) {
Button(onClick = {
TODO()
}) {
Text(text = "Select")
}
}
}
The 'select' button is near the bottom of the code.
First create a sealed class Screen to link radio buttons text to composable as recommended by Google like this:
sealed class Screen(val route: String, val label: String){
object MyRadioGroup: Screen(route = "myRadioGroup", label = "APP NAME")
object DollarStore: Screen(route = "Dollar Store", label = "Dollar Store")
object FreedMyers: Screen(route = "Fred Myers", label = "FreedMyers")}
then modify NavHost or AnimatedNavHost(if you are using accompanist's Navigatio Animatation library as:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
Surface(color = MaterialTheme.colors.background) {
NavHost(navController = navController, startDestination = Screen.MyRadioGroup.route){
composable(Screen.MyRadioGroup.route){
MyRadioGroup(navController = navController)
}
composable(Screen.DollarStore.route){
//Call here the associated composable function
DollarStore()
}
composable(Screen.FreedMyers.route){
//Call here the associated composable function
FreedMyers()
}
}
}
}
}}
Finally add some code to MyRadioGroup Composable
fun MyRadioGroup(navController: NavController) {
val radioOptions = listOf(
"Dollar Store", "Fred Myers",
"Wall Mart", "SafeWay", "Sherm's", "CostCo", "Other"
)
val (selectedOption, onOptionSelected) = remember {
mutableStateOf(radioOptions[1])
}
Scaffold(
topBar = {
TopAppBar(
title = { Text(stringResource(id = R.string.app_name)) },
)
}
) {
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
Column(
modifier = Modifier.padding(start = 16.dp, top = 16.dp)
) {
Text(text = "Select Store from List Below")
Divider()
Text(text = "Then push the 'Select'")
}
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
radioOptions.forEach { text ->
Row(
Modifier
.fillMaxWidth()
.padding(top = 8.dp)
.selectable(
selected = (text == selectedOption),
onClick = { onOptionSelected(text) }
)
.padding(horizontal = 16.dp)
) {
RadioButton(
selected = (text == selectedOption),
modifier = Modifier
.padding(start = 16.dp, top = 12.dp),
onClick = { onOptionSelected(text) }
)
Text(
text = text,
modifier = Modifier.padding(start = 16.dp, top = 16.dp)
)
}
}
}
Column(
modifier = Modifier
.padding(start = 24.dp, top = 24.dp)
) {
Button(
onClick = {
navController.navigate(selectedOption) //navigate to selected route
}
) {
Text(text = "Select")
}
}
}
}}