Home > Software engineering >  How to make LazyColumn reusable
How to make LazyColumn reusable

Time:06-05

When creating a LazyColumn layout, is there a way to modify the items source (i.e. Array<Starters>) to something else so that I can reuse my LazyColumn for a different set of items from a different array?

@Composable
fun MyLazyColumn(lazyItems: Array<Starters>,
                  onClickItem: (Starters) -> Unit
) {
    LazyColumn() {
        items(lazyItems) { choice -> Row() { Text(text = stringResource(id = choice.textResId)) } }
    }
}

Scaffold(
    content = {
        MyLazyColumn(lazyItems = arrayOf(Starters.Canapes,...), onClickItem = startersClickListner)
    }
)

CodePudding user response:

You can create a generic lazyColumn by giving the opportunity for the caller to use the item composable that he want with a @Composable function callback.

Exemple :

@Composable
fun <T> MyLazyColumn(
    lazyItems: Array<T>,
    onClickItem: (T) -> Unit,
    item: @Composable RowScope.(item: T) -> Unit,
) {
    LazyColumn() {
        items(lazyItems) { choice ->
            Row(
                modifier = Modifier.clickable(onClick = { onClickItem(choice) })
            ) {
                item(choice)
            }
        }
    }
}

In your scaffold :

    Scaffold(
        content = {
            MyLazyColumn<Starters>(
                lazyItems = arrayOf(Starters.Canapes, ...),
                onClickItem = startersClickListner
            ) {
                Text(text = stringResource(it.textResId) )
            }
        }
    )

Making the item generic too is not possible if you use class attributes (like this exemple with textRestId)

CodePudding user response:

The answer given by Dinamots is probably the most "Compose" way to go about it. However, if all the things you want to give to the column have a common parent or interface they implement, you can do something like this to get a little more code reuse.

interface Choice {
    val textResId: Int
}

@Composable
fun <T : Choice> ChoiceColumn(
    choices: Array<T>,
    onChoiceClick: ((T) -> Unit) = { }
) {
    BasicLazyColumn(choices, onChoiceClick) {
        Text(stringResource(it.textResId))
    }
}

@Composable
fun <T> BasicLazyColumn(
    choices: Array<T>,
    onItemClick: ((T) -> Unit) = { },
    itemBuilder: @Composable LazyItemScope.(item: T) -> Unit
) {
    LazyColumn {
        items(choices) { choice ->
            Row(Modifier.clickable {
                onItemClick(choice)
            }) {
                itemBuilder(choice)
            }
        }
    }
}
  • Related