1

I am trying to figure out what would be the best approach to create this type of design: https://gyazo.com/bae04894f7ef079a06ad71f733026f33

https://gyazo.com/111eace0d8cdecdecad1c8a7b486faf7

Should I be using a Horizontal lazyRow as suggested with a scrollview or how would I go about doing this? Should I also create 1 composable for each item in placeholdercard or is there a more efficient way to do this with the newer version of jetpack compose? Appreciate the feedback!

This is the code so far:


@Composable
fun MainContent(
    placeholderItems: List<String>
) {

    val lazyListState: LazyListState = rememberLazyListState()

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {

        Text(
            modifier = Modifier
                .padding(16.dp)
                .fillMaxWidth(),
            text = "Example Horizontal LazyRow"
        )

        LazyRow(
            modifier = Modifier.fillMaxWidth(),
            contentPadding = PaddingValues(8.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {

            items(items = placeholderItems) { itemMessage: String ->
                PlaceholderCard(itemMessage)
            }
        }
    }
}

Updated Answer This managed to solve the issues! Thanks to:
@Sadegh.t for suggesting it! - Had to do some tweeks but now it works fully!


data class Items(
    val num: Int,
    val id: UUID = UUID.randomUUID()
)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ItemView(modifier: Modifier = Modifier, title: String, selected:
Boolean = false) {
    Card(
        modifier = if (!selected) modifier
            .height(80.dp)
            .width(95.dp)
        else modifier
            .height(100.dp)
            .width(120.dp),
        shape = RoundedCornerShape(16.dp),
        elevation = if (selected) CardDefaults.cardElevation(24.dp ) else CardDefaults.cardElevation(4.dp)
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically
        ) {

            Text(text = title, modifier = Modifier.fillMaxWidth()
                , textAlign =  TextAlign.Center)
        }
    }
}

@Composable
fun NumberList(list: List<Items>) {

    Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {

        LazyRow(state = rememberLazyListState()) {

            items(50, key = { it }) {
                if (it == 2) {
                    ItemView(
                        title = it.toString(),
                        modifier = Modifier
                            .padding(start = 16.dp, end = 8.dp, bottom = 16.dp, top = 8.dp)
                            .fillMaxWidth()
                            .height(80.dp)
                        , selected = true
                    )
                }else {
                    ItemView(
                        title = it.toString(),
                        modifier = Modifier
                            .padding(start = 16.dp, end = 8.dp, bottom = 16.dp, top = 8.dp)
                            .fillMaxWidth()
                    )
                }
            }
        }
    }
}

Josef M
  • 412
  • 2
  • 5
  • 20
  • Does this answer your question? [Snap to an index Lazyrow](https://stackoverflow.com/questions/71901039/snap-to-an-index-lazyrow) – nglauber Jul 17 '22 at 13:07
  • I think your question is more focused on snapping the items in the center of the screen whereas mine is creating a functional LazyRow with various items. I do find the snapping mechanism interesting though so will look more into it as well :) Thanks for the suggestion! – Josef M Jul 17 '22 at 14:19

2 Answers2

0

You can try this, create a LazyRow and then check if the item is selected or not

@Composable 
fun NumberList(list: List<Items>) {
    Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
        LazyRow(state = rememberLazyListState()) {
            items(list, key = { it.id }) {
                if (it.num == 2) {
                    ItemView(
                        title = it.num.toString(),
                        modifier = Modifier
                            .padding(start = 16.dp, end = 8.dp, bottom = 16.dp, top = 8.dp)
                            .fillMaxWidth()
                            .height(80.dp)
                    , selected = true
                    )
                }else {
                    ItemView(
                        title = it.num.toString(),
                        modifier = Modifier
                            .padding(start = 16.dp, end = 8.dp, bottom = 16.dp, top = 8.dp)
                            .fillMaxWidth()
                    )
                }
            }
        }
    }
}

and for the item:

@Composable
fun ItemView(modifier: Modifier = Modifier, title: String, selected: 
    Boolean = false) {
    Card(
        modifier = if (!selected) modifier
            .height(80.dp)
            .width(95.dp)
        else modifier
            .height(100.dp)
            .width(120.dp),
        shape = RoundedCornerShape(16.dp),
        elevation = if (selected) 24.dp else 4.dp
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically
        ) {

            Text(text = title, modifier = Modifier.fillMaxWidth()
            , textAlign =  TextAlign.Center)
        }
    }
}

Updated: I used this data class you can use your own data class, also it's not necessary to use the Id.

data class Items(val num: Int, val id: UUID = UUID.randomUUID())
Sadegh.t
  • 205
  • 3
  • 10
  • The only problem is that I am getting an error message with id and num, it reads Unresolved reference. – Josef M Jul 17 '22 at 13:34
  • I had to do some additional changes such as with Cardelevation + specify how many items are in the list (will post them as updated changes) but in general it works really well! Appreciate the help! – Josef M Jul 17 '22 at 14:00
  • will add your's as the answer but it needs to be changed a bit as the updated answer shows to be fully functional ( at least for my project!). – Josef M Jul 17 '22 at 14:07
0

This is an alternative version for LazyRow with items which works really well as well!

Update 2022.08.03

I created 2 composables, 1 for the LazyRow and 1 for the Items itself. I also added flingbehaviour (3rd party library, suggested by: nglauber) which allows it to snapp in the middle of the screen without countinuing to "roll" or "swipe" past items as the user swipes left or right!

Here is the result: https://gyazo.com/53f38ed87002efb5676b20c4cd90d58f

Add this to build.gradle(app):

  // Dependency for the LazyRow from dev chrisBane - makes it "snap" in the middle of the screen
    implementation "dev.chrisbanes.snapper:snapper:0.2.2"

LazyRow:

@OptIn(ExperimentalSnapperApi::class, ExperimentalFoundationApi::class)
@Composable
fun LazyContainer() {

    val lazyListState = rememberLazyListState()

    Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {

        LazyRow(
            state = lazyListState,
            flingBehavior = rememberSnapperFlingBehavior(lazyListState)

        ) {

            items(100, key = { it }) {

                ItemView(
                    title = it.toString(),
                    modifier = Modifier
                        .padding(start = 16.dp, end = 8.dp, bottom = 16.dp, top = 8.dp)
                        .fillMaxWidth()
                     

                )

            }
        }
    }
}

Items for display in a LazyRow:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ItemView(

modifier: Modifier = Modifier, 
title: String, 
selected: Boolean = false

) {
    Card(
        modifier = if (!selected) modifier
            .height(120.dp)
            .width(110.dp)
        else modifier
            .height(100.dp)
            .width(120.dp),
        shape = RoundedCornerShape(16.dp),
        elevation = if (selected) CardDefaults.cardElevation(24.dp) else CardDefaults.cardElevation(
            4.dp
        )
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically
        ) {

            Text(
                text = title, modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center
            )
        }
    }
}

Hope this help! Feel free to improve it and modify it on your own, Happy coding!

Josef M
  • 412
  • 2
  • 5
  • 20