ui_controller_view.xml


Overview

`ui_controller_view.xml` is an Android layout file that defines the user interface for a custom video player controller view within the Tubi TV app. It provides an interactive control panel overlay for video playback, including features such as play/pause toggling, seek bar, rewind/forward buttons, subtitle toggling, and ad-related UI elements.

The file uses Android Data Binding to bind UI components directly to a `UserController` view model ([com.tubitv.media.bindings.UserController](/projects/288/68379)), enabling reactive updates of UI elements based on the player state. It leverages ConstraintLayout for flexible positioning and responsiveness and includes custom views such as `VaudTextView`, `StateImageButton`, and `TubiLoadingView` to match Tubi's branding and UX requirements.


Detailed Components and Bindings

Root Elements


1. Controller Panel (ConstraintLayout with id controller_panel)

This panel overlays the video content to show playback controls. It is initially hidden (`android:visibility="gone"`), presumably made visible by the app when the user interacts with the video.

Key UI Elements within Controller Panel:

Component

Description

Binding / Functionality

**`VaudTextView` (id: `view_tubi_controller_title`)**

Shows video title

Bound to `controller.videoName`

**`StateImageButton` (id: `view_tubi_controller_subtitles_ib`)**

Toggles subtitles on/off

Visibility depends on `controller.videoHasSubtitle && !controller.isCurrentAd`.
Click triggers `controller.triggerSubtitlesToggle(!controller.isSubtitleEnabled)`.
Icon changes based on subtitle state.

**`` (id: `view_tubi_controller_ad_description`)**

Includes ad description layout (`view_tubi_ad_learn_more`)

Visible only during ads (`controller.isCurrentAd`).
Passes `controller` as binding variable.

**`ImageButton` (id: `view_tubi_controller_rewind_ib`)**

Rewind 15 seconds

Click triggers `controller.seekBy(-1500 * 10)` (milliseconds).
Hidden during ads (`controller.isCurrentAd`).

**`StateImageButton` (id: `view_tubi_controller_play_toggle_ib`)**

Play/Pause toggle button

Click toggles play state via `controller.triggerPlayOrPause(!controller.isVideoPlayWhenReady)`.
Icon changes depending on play state.
Centered in layout.

**`ImageButton` (id: `view_tubi_controller_forward_ib`)**

Forward 15 seconds

Click triggers `controller.seekBy(1500 * 10)`.
Invisible during ads (`controller.isCurrentAd`).

**`VaudTextView` (id: `view_tubi_controller_elapsed_time`)**

Shows current playback time

Bound to `controller.videoPositionInString` with default fallback string.

**`SeekBar` (id: `view_tubi_controller_seek_bar`)**

Video progress bar

Max bound to video duration.
Progress bound to current time.
Secondary progress bound to buffered position.
Handles touch events and progress changes with controller callbacks:
  - `onProgressChanged`, `onStartTrackingTouch`, `onStopTrackingTouch`.
Touch events disabled if video is an ad.

**`VaudTextView` (id: `view_tubi_controller_remaining_time`)**

Shows remaining playback time

Bound to `controller.videoRemainInString` with default fallback string.

Layout Guidelines

Several vertical and horizontal `Guideline`s are defined for consistent alignment and margins:

These guidelines help position UI elements responsively on different screen sizes.


2. Loading Indicator (TubiLoadingView with id view_tubi_controller_loading)

controller.playerPlaybackState == ExoPlayer.STATE_BUFFERING || controller.playerPlaybackState == ExoPlayer.STATE_IDLE

Variables and Their Roles (from UserController)

Variable / Property

Purpose / Description

`videoName`

Current video's title string

`videoHasSubtitle`

Boolean indicating if video has subtitles

`isSubtitleEnabled`

Boolean subtitle toggle state

`isCurrentAd`

Boolean indicating if the current media is an ad

`isVideoPlayWhenReady`

Boolean indicating if video is playing

`videoPositionInString`

Current playback time as formatted string (e.g., "00:01:23")

`videoRemainInString`

Remaining time as formatted string

`videoDuration`

Total duration of the video in milliseconds

`videoCurrentTime`

Current playback position in milliseconds

`videoBufferedPosition`

Buffered position in milliseconds

`playerPlaybackState`

Current ExoPlayer playback state (buffering, idle, ready, etc.)


Important Implementation Details


Interaction with Other System Components


Usage Example

Assuming this layout is inflated within an activity or fragment, the following is an example of how it might be used:

// Inflate layout with Data Binding
val binding: UiControllerViewBinding = DataBindingUtil.inflate(
    layoutInflater, R.layout.ui_controller_view, parent, false
)

// Create or obtain UserController instance managing playback
val userController = UserController(player, ...)

// Bind controller to layout
binding.controller = userController

// Show controller panel when needed
binding.controllerPanel.visibility = View.VISIBLE

// The UI now reflects the current player state and reacts to user input

Mermaid Diagram: Component Structure and Interactions

classDiagram
    class UserController {
        +String videoName
        +boolean videoHasSubtitle
        +boolean isSubtitleEnabled
        +boolean isCurrentAd
        +boolean isVideoPlayWhenReady
        +String videoPositionInString
        +String videoRemainInString
        +long videoDuration
        +long videoCurrentTime
        +long videoBufferedPosition
        +int playerPlaybackState

        +void triggerPlayOrPause(boolean play)
        +void triggerSubtitlesToggle(boolean enable)
        +void seekBy(int milliseconds)
        +void onProgressChanged(SeekBar, int, boolean)
        +void onStartTrackingTouch(SeekBar)
        +void onStopTrackingTouch(SeekBar)
    }

    class ui_controller_view {
        +VaudTextView view_tubi_controller_title
        +StateImageButton view_tubi_controller_subtitles_ib
        +ViewGroup view_tubi_controller_ad_description
        +ImageButton view_tubi_controller_rewind_ib
        +StateImageButton view_tubi_controller_play_toggle_ib
        +ImageButton view_tubi_controller_forward_ib
        +VaudTextView view_tubi_controller_elapsed_time
        +SeekBar view_tubi_controller_seek_bar
        +VaudTextView view_tubi_controller_remaining_time
        +TubiLoadingView view_tubi_controller_loading
    }

    ui_controller_view --> UserController : binds to

Summary

`ui_controller_view.xml` defines a rich, data-bound video playback controller UI for the Tubi TV app. By leveraging Android Data Binding and ConstraintLayout, it provides a responsive, interactive overlay with play controls, time displays, subtitle toggling, and ad awareness. The layout communicates closely with the `UserController` view model to reflect real-time playback state and handle user interactions seamlessly.

This modular design allows the controller UI to be reused and easily maintained, while providing users with intuitive and responsive video controls consistent with the Tubi brand.