如何为不同的布局重用点击监听器

How to reuse click listeners for different layouts

我的应用程序针对不同的设备类型包含 2 种不同的布局。我想要执行不同的操作,例如第 1、2 和 3 项导航到不同的屏幕,第 4 项显示 Toast,第 5 项启动电子邮件编辑器意图,等等。有没有办法找出数组的哪个索引被单击并制作这些点击事件可重用而不是两次创建相同的点击事件?

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

只需将您的 click-codeblocks 存储为变量。

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

像这样使用

FirstItem(
 Modifier.clickable { firstItemClicker() }
)

或者,

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

由于我们使用的是 Compose,因此我们可以利用 Kotlin。 我们可以创建一个枚举 class,而不是创建一个 string-array 资源,所有的选择都是这样的:

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

然后,我们可以像这样设置您的 LazyColumnLazyGrid

@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) }
           )
        }
    // ...
}

要重用 ClickListener,我们可以创建一个 lambda 对象并重用它:

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