channel page: park the grid unconditionally, tighter header band
The old park ran only while `firstVisibleItemIndex > 0`, but the focus pull that hands the first card its focus leaves the header row at index 0 while slid up by ~96 dp — so the guard never fired and the top of the channel header stayed clipped off screen (#31 review). scrollToItem(0) re-anchors both index and offset. The banner band drops to 116 dp with a 40 dp description strip, so the whole header is under one card row: the grid never reflows around it and the header stays fully on screen when the first card takes focus. Addresses #27, #31.
This commit is contained in:
parent
b9419e6a65
commit
f371a21e17
1 changed files with 13 additions and 7 deletions
|
|
@ -92,10 +92,14 @@ fun VideoListScreen(
|
||||||
// handing the first card the focus animates the grid up (a focused card
|
// handing the first card the focus animates the grid up (a focused card
|
||||||
// that sits partly off-screen is pulled into view), and this effect then
|
// that sits partly off-screen is pulled into view), and this effect then
|
||||||
// snapped it back down — the jump that was still reported on the channel
|
// snapped it back down — the jump that was still reported on the channel
|
||||||
// page when the first video got focus (#27 review). Doing the park first,
|
// page when the first video got focus (#27 review).
|
||||||
// and only while the grid is actually displaced, leaves nothing to undo.
|
// The park has to be unconditional, and has to reset the row's offset,
|
||||||
|
// not just its index: the focus pull leaves the header row at index 0 but
|
||||||
|
// slid up by ~96 dp, so a guard on firstVisibleItemIndex > 0 never fires
|
||||||
|
// in that state and the top of the channel header stays clipped off
|
||||||
|
// screen (#31 review). scrollToItem(0) re-anchors both.
|
||||||
LaunchedEffect(items.isNotEmpty(), source) {
|
LaunchedEffect(items.isNotEmpty(), source) {
|
||||||
if (items.isNotEmpty() && gridState.firstVisibleItemIndex > 0) {
|
if (items.isNotEmpty()) {
|
||||||
runCatching { gridState.scrollToItem(0) }
|
runCatching { gridState.scrollToItem(0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -436,12 +440,14 @@ private fun ChannelHeader(
|
||||||
.clip(androidx.compose.foundation.shape.RoundedCornerShape(12.dp))
|
.clip(androidx.compose.foundation.shape.RoundedCornerShape(12.dp))
|
||||||
.background(Color.Black),
|
.background(Color.Black),
|
||||||
) {
|
) {
|
||||||
// Banner area: a fixed height with the identity + stats anchored to its
|
// Banner area: 116 dp, with the identity + stats anchored to its bottom; the
|
||||||
// bottom; the description sits in the black strip below it.
|
// description sits in the black strip below it. The whole band is 160 dp
|
||||||
|
// (4 + 116 + 40) — under one card row — so the grid never reflows around it
|
||||||
|
// and the band stays fully on screen when the first card takes focus (#31).
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(178.dp)
|
.height(116.dp)
|
||||||
.background(androidx.compose.ui.graphics.Brush.linearGradient(accent)),
|
.background(androidx.compose.ui.graphics.Brush.linearGradient(accent)),
|
||||||
) {
|
) {
|
||||||
if (banner != null) {
|
if (banner != null) {
|
||||||
|
|
@ -563,7 +569,7 @@ private fun ChannelHeader(
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(42.dp)
|
.height(40.dp)
|
||||||
.padding(start = 16.dp, end = 16.dp, top = 6.dp),
|
.padding(start = 16.dp, end = 16.dp, top = 6.dp),
|
||||||
) {
|
) {
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue