Как получить onFocusChanged ивент в LazyRow для каждого элемента в списке?
Я работаю над реализацией accessibility (для людей с ограниченными возможностями, включая незрячих), когда пользователь свайпает влево или вправо, чтобы переместить фокус между элементами списка LazyRow, мне нужно знать индекс элемента в списке, который в данный момент находится в фокусе accessibility.
У меня есть реализация:
LazyRow(
state = listState,
modifier = modifier,
flingBehavior = rememberSnapFlingBehavior(lazyListState = listState)
) {
itemsIndexed(items = episodes, key = { index, _ ->
"$CARD_KEY$index"
}) { index, item ->
item.apply {
CustomCard(
episode = item.episode,
modifier = Modifier
.wrapContentWidth()
.background(
BrandedTheme._ui_core__bottomsheet__backgroundColor
)
.onFocusChanged {
if (it.isFocused) {
if (listState.isScrollInProgress.not() && selectedEpisodeIndex != -1) {
GlobalScope.launch {
listState.scrollToItem(index = index)
}
}
}
}
.wrapContentHeight()
.semantics(mergeDescendants = true) {
isTraversalGroup = true
traversalIndex = -1f
},
index = index
)
}
}
}
Таким образом, каждый элемент в списке имеет модификатор с свойством - onFocusChanged. Проблема в том, что это событие срабатывает только при инициализации списка, а затем, когда пользователь перемещает фокус доступности (свайпает влево/вправо), то я вижу на экране девайса, что следующий элемент в списке получает фокус, но в коде событие onFocusChanged не срабатывает.
Что я упускаю здесь?
UPD
Добавил onFocusEvent()
и focusTarget()
, теперь вроде как получаю ивент смены элементов, но 2 проблемы:
- Все элементы имеею стейт
Inactive
(ни одного active) - Индекс не отображает индекс того элемента который сейчас на экране
LazyRow(
state = listState,
modifier = modifier,
flingBehavior = rememberSnapFlingBehavior(lazyListState = listState)
) {
itemsIndexed(items = episodes, key = { index, _ ->
"$CARD_KEY$index"
}) { index, item ->
item.apply {
CustomCard(
episode = item.episode,
modifier = Modifier
.wrapContentWidth()
.onFocusEvent {
Log.e("HERE", "111 onFocusEvent: $index :: $it")
}
.background(
BrandedTheme._ui_core__bottomsheet__backgroundColor
)
.onFocusChanged {
if (it.isFocused) {
if (listState.isScrollInProgress.not() && selectedEpisodeIndex != -1) {
GlobalScope.launch {
listState.scrollToItem(index = index)
}
}
}
}
.focusTarget()
.wrapContentHeight()
.semantics(mergeDescendants = true) {
isTraversalGroup = true
traversalIndex = -1f
},
index = index
)
}
}
}
Была еще другая идея - я пробовал сделать кастомную rememberSnapFlingBehavior
так как обратил внимание, что в accessibility mode фокус на экране переключается и он подтягивает следующий элемент, но он не устанавливается по центру экрана (хотя это работает без accessibility mode). Но в итоге эта идея тоже не заработала.