Skip to content

Add Android TV UI module with UIController - #124

Open
MattiasBuelens wants to merge 3 commits into
feature/tv-keyboardfrom
feature/tv-skeleton
Open

MattiasBuelens wants to merge 3 commits into
feature/tv-keyboardfrom
feature/tv-skeleton

Conversation

@MattiasBuelens

@MattiasBuelens MattiasBuelens commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds a new :ui-tv module (artifact com.theoplayer.android-ui:android-ui-tv, package com.theoplayer.android.ui.tv) with a UIController that is controlled with a TV remote. It builds on :ui-common and androidx.tv:tv-material, and doesn't depend on :ui or Material3. All public API is opt-in through the new @ExperimentalTvUiApi.

@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalTvUiApi

@ExperimentalTvUiApi @Composable
fun THEOplayerTvTheme(
    colorScheme = darkColorScheme(),
    typography = MaterialTheme.typography,
    playerAnimations = PlayerAnimations(controlsHideDelay = 5.seconds),
    content
)

@ExperimentalTvUiApi @Composable
fun UIController(
    modifier = Modifier,
    theoplayerView: THEOplayerView,
    color = Color.Black.copy(alpha = 0.5f),
    centerOverlay, errorOverlay, topChrome, centerChrome, bottomChrome // same slots as mobile
)

Shared controller core

The mobile and TV controllers now share their layout-independent logic through @InternalUiApi building blocks in :ui-common:

  • rememberControlsVisibility(firstPlay, paused, forceVisible, hideDelay): when the controls are shown or hidden, plus the auto-hide timer.
  • rememberUIControllerScope(theoplayerView, player) and rememberUIState(scope, errorState, pictureInPictureState): the menu stack and which state is active (Error, Menu, Controls or Hidden).
  • UIControllerCore(...): provides LocalPlayer, LocalTHEOplayerView and LocalUIControllerErrorState, closes an open menu on Back, applies handlePlayerKeys, and renders the background, the content transition and the slot layout. Renderers pass their own contentTransform, plus an extra modifier and controlsModifier.

Mobile keeps tap-to-toggle, playerAspectRatio, casting and slide transitions for menus. TV adds its own D-pad and Back handling plus focus, and uses fade transitions.

PlayerAnimations (and LocalPlayerAnimations) moved to :ui-common. The package is still com.theoplayer.android.ui.theme. It has a new controlsHideDelay (2 s by default) that sets how long the controls stay visible after user interaction. Both themes take playerAnimations.

Changes on mobile:

  • Pressing Back now closes an open menu.
  • PlayerAnimations.controlsHideDelay can be configured.
  • Breaking: adding the constructor parameter changes the binary signatures of PlayerAnimations' constructor and copy.

TV UIController behavior

  • Controls visibility: the controls are always shown before the first play and while paused. While playing, they hide after controlsHideDelay (5 s on TV) without key presses.
  • Keys: the shared handlePlayerKeys means any key shows the controls, and media keys work even while the controls are hidden. While the controls are hidden, Center/Enter toggles play/pause and Left/Right seek ±10 s, and each of these also shows the controls. While they are visible, keys go to the focused control. An open menu or the error overlay always receives keys.
  • Back: closes the open menu, otherwise hides the controls. It falls through to the app when the controls are already hidden, before the first play, or while the error overlay is shown.
  • Focus: when the controls appear or a menu closes, focus moves into the controls (focusRestorer + focusGroup). It lands on the first focusable control or returns to the last focused one.

Robolectric tests in :ui-tv cover key handling, auto-hide, Back, focus and errors. A new :ui test covers Back closing a menu on mobile.

Link to Devin session: https://dolby.devinenterprise.com/sessions/6307f9268b9b47fbab4169cde6216af1
Open in Devin Desktop: https://dolby.devinenterprise.com/desktop/session/6307f9268b9b47fbab4169cde6216af1?variant=devin
Requested by: @MattiasBuelens

@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@MattiasBuelens
MattiasBuelens added this pull request to stack #123 October 14, 2026 15:39
@devin-ai-integration
devin-ai-integration Bot force-pushed the feature/tv-skeleton branch 2 times, most recently from c9a7d31 to 83559dd Compare October 14, 2026 15:56
MattiasBuelens and others added 3 commits October 15, 2026 11:05
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant