Fixing seek text label overlap and visibility issues. (#923)

## Description
- Smoothly bumps up the title and subtitle text above the seek progress
label when the seek bar is focused to prevent overlap.
- Adds a semi-transparent black backer to the text label that appears
above the seek progress indicator. Helps with visibility when the image
in the playback matches the color of the text. Note: the backer is black
with Alpha of 0.6 for now because I felt that looked good for contrast
across all themes. However, if you prefer it respect a particular theme
color, I'd be willing to make that change.

### Related issues
In the playback screen, when focusing the seek bar on Android TVs (at
least the ones I was able to test), the seek text above the seek bar
will overlap with the media title. This is a purely cosmetic issue in
the UI, but it seemed worth a fix. See before and after images in in the
Screenshots section below

This problem is briefly mentioned in point number 2 of [#528
](https://github.com/damontecres/Wholphin/issues/528)

### Testing
Tested manually on TCL model 50S434 running Android TV. Tested manually
using AVD emulation on Television (1080p) and Television (4K) preset
devices. Reproduced the problem on all 3 devices and confirmed that my
fix works across all.

## Screenshots
Before:
<img width="2046" height="1184" alt="before"
src="https://github.com/user-attachments/assets/64708e13-3fa4-4248-91e3-e203f8ac1f7d"
/>

After:
<img width="2046" height="1183" alt="after"
src="https://github.com/user-attachments/assets/db9d1767-cf93-4153-b13a-9a18fbc89e0c"
/>

## AI or LLM usage
None

---------

Co-authored-by: Ray <154766448+damontecres@users.noreply.github.com>
This commit is contained in:
Cristiano Chelotti 2026-02-19 16:18:20 -05:00 committed by GitHub
parent c488c05c12
commit 8bfe77e6e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,6 +1,7 @@
package com.github.damontecres.wholphin.ui.playback package com.github.damontecres.wholphin.ui.playback
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideInVertically
@ -18,10 +19,12 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -443,6 +446,10 @@ fun PlaybackOverlay(
text = (seekProgressMs / 1000L).seconds.toString(), text = (seekProgressMs / 1000L).seconds.toString(),
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
modifier =
Modifier
.background(Color.Black.copy(alpha = 0.6f), shape = RoundedCornerShape(4.dp))
.padding(horizontal = 8.dp, vertical = 4.dp),
) )
} }
} }
@ -525,13 +532,22 @@ fun Controller(
seekBarInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() }, seekBarInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() },
onNextStateFocus: () -> Unit = {}, onNextStateFocus: () -> Unit = {},
) { ) {
val seekBarFocused by seekBarInteractionSource.collectIsFocusedAsState()
val verticalOffset by animateDpAsState(
targetValue = if (seekBarFocused) (-32).dp else 0.dp,
label = "TitleBumpOffset",
)
Column( Column(
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = modifier, modifier = modifier,
) { ) {
Column( Column(
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.padding(start = 16.dp), modifier =
Modifier
.padding(start = 16.dp)
.offset(y = verticalOffset),
) { ) {
title?.let { title?.let {
Text( Text(