I am using TvLazyColumn
composable with 7 items, and inside of each item has a title and a TvLazyRow
with a list of video thumbnail images which are focusable.
Out of the 7 items, 6 have identical header style (1 row header text) so the padding between the header and the TvLazyRow
is identical. However, one item has a different header style (multiple-row header: LIVE badge, title row, information row).
When I scroll up and down the TvLazyColumn
using D-pad, I want the top of each column item to be aligning with the top of TvLazyColumn
, regardless of the focused thumnail image's vertical position. This means I want the column pivot to be set on the top of the title of each column items, and not on the thumbnail images.
If all 7 items have the identical 1 row text header style, I can simply adjust PivotOffset
to achieve this. But I can't do so because the one item has different header style. Could someone please help me achieving this desired behavior?
From here:
If I press DOWN on my D-Pad
This is what I want:
But this is what I get instead - Notice the LIVE badge goes out of the bound:
Here is the code snippets:
TvLazyColumn(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.5f)
.border(width = 2.dp, color = Color.Red)
.align(Alignment.BottomStart),
pivotOffsets = PivotOffsets(parentFraction = 0.3f, childFraction = 0.2f),
contentPadding = PaddingValues(bottom = 100.dp),
) {
.
.
.
if (homeViewState.userHistoryList.isNotEmpty()) {
item {
WTvMediaPostRow(
postList = homeViewState.userHistoryList,
title = stringResource(id = ...),
onPostClick = onItemClick,
onItemFocus = onItemFocus,
)
}
}
if (homeViewState.liveList.isNotEmpty()) {
item {
WTvLivePostRow(
postList = homeViewState.liveList,
title = stringResource(id = ...),
showLiveBadge = true,
onPostClick = onItemClick,
onItemFocus = onItemFocus,
)
}
}
.
.
.
}
I tried setting different pivotOffsets
value for the one item with different header style and it sort of works - the offset gets applied ONLY AFTER I start scrolling the TvLazyRow
inside the column item. I want the offset to be applied as soon as the thumbnail gets focused.
var currentFocusRowType by remember { mutableStateOf(WTvHomeRowType.EMPTY) }
TvLazyColumn(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.5f)
.border(width = 2.dp, color = Color.Red)
.align(Alignment.BottomStart),
pivotOffsets = if (currentFocusRowType == WTvHomeRowType.ON_LIVE) {
PivotOffsets(parentFraction = 0.5f, childFraction = 0.2f)
} else {
PivotOffsets(parentFraction = 0.3f, childFraction = 0.2f)
},
) {
.
.
.
if (homeViewState.liveList.isNotEmpty()) {
item {
WTvLivePostRow(
postList = homeViewState.liveList,
title = stringResource(id = ...),
showLiveBadge = true,
onPostClick = onItemClick,
onItemFocus = { index, post ->
currentFocusRowType = WTvHomeRowType.ON_LIVE
onItemFocus.invoke(index, post)
},
)
}
}
.
.
.
}
I tried setting different pivotOffsets value for the one item with different header style and it sort of works - the offset gets applied ONLY AFTER I start scrolling the TvLazyRow inside the column item. I want the offset to be applied as soon as the thumbnail gets focused.
In case anyone is facing the same issue, I was able to achieve the desired outcome by setting userScrollEnabled = false
and use rememberTvLazyListState().scrollToItem()
to manually scroll to each category when there's up & down D-pad input.
Here is the code snippet:
val tvLazyListState = rememberTvLazyListState()
val homeCategorySize = remember { mutableIntStateOf(7) }
val currentIndex = remember { mutableIntStateOf(0) }
TvLazyColumn(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.5f)
.align(Alignment.BottomStart)
.handleDPadKeyEvents(
onDown = {
coroutineScope.launch {
currentIndex.intValue = (++currentIndex.intValue).coerceIn(0, homeCategorySize.intValue - 1)
tvLazyListState.scrollToItem(currentIndex.intValue)
}
false
},
onUp = {
coroutineScope.launch {
currentIndex.intValue = (--currentIndex.intValue).coerceIn(0, homeCategorySize.intValue - 1)
tvLazyListState.scrollToItem(currentIndex.intValue)
}
false
},
),
state = tvLazyListState,
userScrollEnabled = false,
contentPadding = PaddingValues(bottom = 100.dp),
) {
...
}
.handleDPadKeyEvents
is an extension function I created using Modifier.onPreviewKeyEvents
to handle certain key inputs differently.
The above method scrolls the TvLazyColumn to bring the view of the complete children as I wanted. Hope this helps to anyone facing similar issues.