Issue
My app contains 2 different layouts for different device types. I want different actions to be performed e.g. 1st, 2nd and 3rd items to navigate to different screens, 4th item to show a Toast
, the 5th item to launch an email composer intent, etc. Is there way to find out which index of the array was clicked and making these click events reusable rather than creating the same click event twice?
array in strings.xml
<string-array name="array_main">
<item>@string/breads</item>
<item>@string/cakes</item>
<item>@string/condiments</item>
<item>@string/desserts</item>
<item>@string/snacks</item>
<item>@string/contact us</item>
</string-array>
MainActivity.kt
class ActivityMain : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
HomeScreen(navController = rememberNavController())
}
}
}
}
@Composable
fun ComposeNavigation() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home_screen"
) {
composable("home_screen") {
HomeScreen(navController = navController)
}
composable("second_screen") {
SecondScreen(navController = navController)
}
composable("third_screen") {
ThirdScreen(navController = navController)
}
}
}
@Composable
fun HomeScreen(navController: NavController) {
val windowInfo = rememberWindowInfo()
if (windowInfo.screenWidthInfo is WindowInfo.WindowType.Compact) {
Scaffold(
topBar = {...},
content = {
MyLazyColumn(lazyItems = resources.getStringArray(R.array.array_main))
},
)
} else {
Scaffold(
topBar = {...},
content = {
MyLazyVerticalGrid(lazyItems = resources.getStringArray(R.array.array_main))
},
)
}
}
}
MyLazyColumn.kt
@Composable
fun MyLazyColumn(lazyItems: Array<String>) {
val listState = rememberLazyListState()
LazyColumn(
state = listState,
) {
items(lazyItems) { item ->
Row(modifier = Modifier
.fillMaxWidth()
.clickable {
}) {
Text(
text = item,
)
}
}
}
}
MyLazyVerticalGrid.kt
fun MyLazyVerticalGrid(lazyItems: Array<String>) {
val lazyGridState = rememberLazyGridState()
LazyVerticalGrid(
state = lazyGridState,
columns = GridCells.Fixed(2),
content = {
items(lazyItems.size) { index ->
OutlinedButton(
modifier = Modifier.padding(7.dp),
onClick = {/*TODO*/ }) {
Text(text = lazyItems[index]
)
}
}
}
)
}
Solution
Since we're using Compose, we can take advantage of Kotlin.
Instead of creating a string-array
resource, we can create an enum class with all the choices like this:
enum class Choices(@StringRes val textResId: Int) {
Breads(R.string.breads),
Cakes(R.string.cakes),
Condiments(R.string.condiments),
Desserts(R.string.desserts),
Snacks(R.string.snacks),
ContactUs(R.string.contact_us),
}
Then, we can setup your LazyColumn
and LazyGrid
like this:
@Composable
fun MyLazyColumn(
lazyItems : Array<Choice>,
onClickItem: (Choice) -> Unit
) {
//...
items(lazyItems) { choice ->
//...
Text(text = stringResource(choice.textResId))
Button(
//...
onClick = { onClickItem(choice) }
)
//...
}
//...
}
@Composable
fun MyLazyGrid(
lazyItems : Array<Choice>,
onClickItem: (Choice) -> Unit
) {
// ...
items(lazyItems) { choice ->
Text(text = stringResource(choice.textResId))
Button(
onClick = { onClickItem(choice) }
)
}
// ...
}
To reuse the ClickListener
, we can create a lambda object and reuse it:
@Composable
fun HomeScreen(/* ... */) {
val listener: (Choice) -> Unit = { choice ->
when(choice) {
Breads -> {}
Cakes -> {}
Condiments -> {}
Desserts -> {}
Snacks -> {}
ContactUs -> {}
}
}
MyLazyGrid(
lazyItems = arrayOf(
/* Choice items you'd add to you list */
),
onClickItem = listener
)
MyLazyColumn(
lazyItems = arrayOf(
/* Choice items you'd add to you list */
),
onClickItem = listener
)
}
Answered By - Harry Luu
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.