Уменьшить непрозрачность элементов, не находящихся в фокусе

У меня есть список элементов, которые отображаются на главном экране, список можно прокручивать по вертикали. На данный момент у меня есть 5 элементов, но элементы добавляются, когда пользователь приближается к последнему элементу, создавая бесконечную прокрутку.

Я хочу, чтобы все элементы исчезли, но тот, что в фокусе, должен быть полностью прозрачным, например:

Как вы можете видеть, элементы слева и справа затемнены и немного меньше, в то время как элемент в фокусе полностью прозрачен и немного больше, что указывает на то, что это элемент в фокусе.

Это то, что у меня есть до сих пор:

Я изо всех сил пытаюсь достичь этого.

Это мое Composableсписок:

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

И 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 {
            Icon(model.mIcon)
        }
    }
}

@Composable
private fun Icon(id: Int) {
    Image(
        painter = painterResource(id = id),
        contentDescription = null,
        contentScale = ContentScale.Crop,
        modifier = Modifier
            .padding(20.dp)
            .size(100.dp)
    )
}

Кто-нибудь знает, как мне этого добиться?

2 ответа

Вы можете использовать состояние списка, чтобы определить, насколько далеко каждый элемент находится от центра, и соответствующим образом применить непрозрачность:

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

Результат:

добавлять isFocusedпараметр для HomeScreenItemобрабатывать его состояние.

Теперь обработайте этот параметр на основе некоторого условия, когда этот конкретный элемент попадет в фокус.

Условие для получения элемента в фокусе:

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

или иметь некоторую пользовательскую логику для этого.

Другие вопросы по тегам