0

I have a list of items which are displayed on the home screen, the list is vertically scrollable. At the moment I have 5 items but items are added as the user approaches the last item creating an infinite scroll.

I want to have all the items faded out but the one in focus should be fully trasparent like so:

enter image description here

As you can see the item to the left and right are faded and are a little smaller whilst the item in focus is fully transparent and is slightly bigger indicating that this is the item in focus.

This is my Composable list:

@Composable
fun HomeScreenList() {
    val homeScreenItems = getItems()
    val listState = rememberLazyListState(Int.MAX_VALUE / 2)
    LazyRow(
        state = listState,
        modifier = Modifier
            .fillMaxWidth(),
        contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
    ) {
        items(Int.MAX_VALUE, itemContent = {
            val index = it % homeScreenItems.size
            HomeScreenItem(model = homeScreenItems[index])
        })
    }
}

And the HomeScreenItem:

@Composable
fun HomeScreenItem(model: HomeScreenViewModel) {
    Card(
        modifier = Modifier
            .padding(horizontal = 10.dp, vertical = 20.dp),
        elevation = 2.dp,
        backgroundColor = model.mBackgroundColor,
        shape = Shapes.large,
    ) {
        Row {
             Image(
        painter = painterResource(id = model.mIcon),
        contentDescription = null,
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .padding(20.dp)
            .size(100.dp)
    )
        }
    }
}

Does anyone know how I should achieve this?

KTOV
  • 559
  • 3
  • 14
  • 39
  • Can you update project to the github and share it, I can help. – RaBaKa 78 Feb 26 '22 at 02:42
  • sorry I'will be busy for some days, but you can refer this post https://medium.com/@Rieger_san/create-a-chipgroup-with-jetpack-compose-f4744b94fa34 – RaBaKa 78 Feb 26 '22 at 12:55

2 Answers2

2

You can use the list state to determine how far away each item is from the center, and apply opacity accordingly:

val homeScreenItems = remember {
    listOf(
        Icons.Default.Person,
        Icons.Default.Usb,
        Icons.Default.Keyboard,
    )
}
val listState = rememberLazyListState(Int.MAX_VALUE / 2)
val (rowHalfSize, setRowHalfSize) = remember { mutableStateOf<Int?>(null) }
val horizontalContentPadding = 16.dp
val density = LocalDensity.current
LazyRow(
    state = listState,
    contentPadding = PaddingValues(horizontal = horizontalContentPadding, vertical = 8.dp),
    modifier = Modifier
        .fillMaxWidth()
        .onSizeChanged {
            setRowHalfSize(it.width / 2 - with(density) { horizontalContentPadding.roundToPx() })
        }
) {
    items(Int.MAX_VALUE) { globalIndex ->
        val index = globalIndex % homeScreenItems.size
        val opacity by remember(rowHalfSize) {
            derivedStateOf {
                if (rowHalfSize == null) return@derivedStateOf 0.5f
                val currentItemInfo = listState.layoutInfo.visibleItemsInfo
                    .firstOrNull() { it.index == globalIndex }
                    ?: return@derivedStateOf 0.5f
                val itemHalfSize = currentItemInfo.size / 2
                (1f - minOf(1f, abs(currentItemInfo.offset + itemHalfSize - rowHalfSize).toFloat() / itemHalfSize) * 0.5f)
            }
        }
        Icon(
            homeScreenItems[index], null,
            modifier = Modifier
                .alpha(opacity)
                .scale(opacity)
        )
    }
}

Result:

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
-1

add isFocused param for HomeScreenItem to handle its state.

Now handle this param based on some condition, when that particular item will get in focus.

Condition to get the item in focus:

val scrollState = rememberLazyListState()
val focusableIndex = scrollState.firstVisibleItemIndex + scrollState.layoutInfo.visibleItemsInfo.size/2

or have some custom logic to do that.