Home > Blockchain >  How to reuse click listeners for different layouts
How to reuse click listeners for different layouts

Time:05-13

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]
                    )
                }
            }
        }
    )
}

CodePudding user response:

Just store your click-codeblocks as variables.

val firstItemClicker = { /* Add Actions Here */ }
val secondItemClicker = { /* and So on */ }

Use it like

FirstItem(
 Modifier.clickable { firstItemClicker() }
)

Or,

Button(
 onclick = { firstItemClicker() }
){
 Text("Click Recyler")
}

CodePudding user response:

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(
       onClickItem = listener
    )
    MyLazyColumn(
       onClickItem = listener
    )
}
  • Related