Уменьшить непрозрачность элементов, не находящихся в фокусе
У меня есть список элементов, которые отображаются на главном экране, список можно прокручивать по вертикали. На данный момент у меня есть 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
или иметь некоторую пользовательскую логику для этого.