Skip to content

Expose fine-grained UI element visibility through 'PlayerView.ControllerVisibilityListener' #229

Open

Description

@warren-bank

Media3 Version

1.0.0-beta03

Devices that reproduce the issue

BOXD6 (TV box) running Android 7.1.2

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Not tested

Reproduction steps

observed in app: ExoAirPlayer v3.x

Expected result

listener receives event notifications without any delay.. immediately after the controller is hidden

Actual result

approx. 3 second delay


When I migrated a project from ExoPlayer to Media3, I needed to change from the old PlayerView to the new PlayerView (aka: StyledPlayerView)

Media

N/A

Bug Report

  • You will email the zip file produced by adb bugreport to [email protected] after filing this issue.

Activity

  1. self-assigned this
    on Dec 19, 2022
  2. icbaker commented on Dec 19, 2022

    @icbaker
    Collaborator

    initially, the code had called: PlayerView.setControllerVisibilityListener(PlayerControlView.VisibilityListener)

    • this listener didn't receive any event notifications (at all)

    I can reproduce this, it's definitely not expected (even though it's deprecated we expected it still to work) and I've found the problem in the code - I've sent a fix for review internally. Thanks for reporting!


    when the visibility of the controller changes:

    • from GONE to VISIBLE, the listener receives an event notification immediately
    • from VISIBLE to GONE, the listener receives an event notification after a delay (approx. 3 seconds)

    The PlayerControlView has three visibility states:

    1. Transport controls and progress bar visible with position & duration
    2. Only progress bar visible
    3. Nothing visible

    If you don't touch the screen then it transitions from 1 -> 2 -> 3 with a delay between each. It only emits the GONE visibility when transitioning to 3, because until that point some of the control view is still visible. Is it possible this is the delay you're seeing? If it's not, then I'm afraid I'm not able to reproduce the problem you're seeing.

  3. warren-bank commented on Dec 19, 2022

    @warren-bank
    Author

    What I observe is..

    The following list summarizes all of the UI elements of the controller:

    1. a partly transparent modal overlay that darkens the entire PlayerView
    2. in the vertical middle of the View, a horizontal row of controls: previous, rewind, pause/play, fast-forward, next
    3. at the bottom of the View, a horizontal row with: current time, overall time, repeat mode, overflow
    4. immediately above the previous row: a horizontal progress/seek bar

    In terms of timing:


    Your explaination that there are 3 visibility states, and each transition can actually be broken down into 2x sub-transitions, makes perfect sense and puts the above observations into proper context.

    In terms of the 3 visibility states (as you defined them):

    Would it make sense to expose the intermediate transition (in both directions) to the PlayerView.ControllerVisibilityListener.onVisibilityChanged(int visibility)?

    • since the method signature needs to remain the same, perhaps additional integer constant values could be used
    • if.. the transition from GONE to VISIBLE does (in fact) happen without any intermediate delay
      • which.. makes perfect sense, since it would be horrible UX to make the user wait
      • then.. only the transition from VISIBLE to GONE needs an intermediate event
        • an easy (but hacky) solution could notify the event listener:
          • View.INVISIBLE to indicate: 1 > 2
          • View.GONE to indicate: 2 > 3

    I know.. I know.. hacky.
    In a perfect world, we'd have more contants to choose from.
    (ex: View.PARTLY_GONE and View.PARTLY_VISIBLE)
    Thoughts?


    Off-topic, but in terms of UX:

    • during visibility state 2
      • the horizontal progress/seek bar is the only controller UI element still visible
      • this appears as only a thin white line at the bottom border of the PlayerView
      • wouldn't it be nicer to also keep element 3 visible.. beneath 4,
        as users are familiar seeing the two together?

    Actually, it isn't that off-topic, because if this were the case..
    then I wouldn't mind my custom UI elements remaining visible during visibility state 2.
    It's only because they are left alone on the screen (for a brief delay) that it feels buggy.


    I haven't looked at the main demo app in a while, but if memory serves..
    I believe it has some custom UI elements that should also be effected in the same way..
    by using the event listener to conditionally hide or show the elements.
    A debug button that opens a dialog window?

    nag: I wish prebuilt APKs (without decoder extensions) for the demo apps were available (as release attachments).

    update: yes.. this

  4. icbaker commented on Jan 16, 2023

    @icbaker
    Collaborator

    I'm going to turn this into an enhancement to track exposing more fine-grained visibility changes via PlayerView.ControllerVisibilityListener. We don't have immediate plans to work on this, but we would accept a high quality PR.

    Rather than passing additional constants to the existing method, I suggest we add a new default method to the interface, something like:

    default void onElementVisibilityChange(@PlayerView.UiElement int elements, int visibility, long animationDurationMs);

    And we would also defined the @UiElement flag IntDef with values like:

    public static final int UI_ELEMENT_PROGRESS_BAR = 1;
    public static final int UI_ELEMENT_LOWER_CONTROLS = 1 << 1;
    public static final int UI_ELEMENT_CENTER_CONTROLS = 1 << 2;

    Then we would call this method to indicate which parts of the UI are being shown/hidden. I think we would make sure to call it at the start of animations, so an app can then choose how to 'sync up' with the animation (or wait until it's complete).

    An app that cares about specific parts of the UI can listen to this method, and ignore the single-int variant. An app that only cares about all the controls being hidden/visible can listen to the single-int variant.

    We don't have any plans to make changes to the other parts of the UI you've commented on (e.g. the way the progress bar remains visible when other parts are hidden). If you need to customise the behaviour of our UI components to this degree, you may want to consider writing your own: https://exoplayer.dev/ui-components.html#further-customization

    Unfortunately we are unable to provide demo app APKs (google/ExoPlayer#1920), but we do provide instructions for building and installing them from source without Android Studio: https://github.com/androidx/media/tree/release/demos#using-gradle-from-the-command-line

  5. changed the title [-][bug] significant delay before 'PlayerView.ControllerVisibilityListener' is notified that controller is GONE[/-] [+]Expose fine-grained UI element visibility through 'PlayerView.ControllerVisibilityListener'[/+] on Jan 16, 2023
  6. warren-bank commented on Jan 16, 2023

    @warren-bank
    Author

    I like your idea a lot; it provides the listener full knowledge of all such UI transitions.

    My only immediate comment..
    purely as a convience to the listener, so delay timers don't need to be reimplemented again and again..
    would be that this event handler be called both at the start and end of every element animation.

    • an animationDurationMs that is positive (non-zero) indicates that an animation is starting
      • the listener could choose to post a runnable to its own handler with some custom delay
      • or.. presumably, in 99.9% of use cases.. the listener could do nothing and wait for a 2nd event for the same elements
    • an animationDurationMs that is exactly zero indicates that either an animation is complete, or there was no animation at all
      • either way.. the elements now have visibility
  7. added a commit that references this issue on Mar 21, 2023
  8. added a commit that references this issue on Jun 22, 2023
  9. batadamnjanovic commented on Jul 27, 2023

    @batadamnjanovic

    Hi! Any news about this? I can't rely on the controller visibility states, as the UI does not look really nice when I do.
    This is the best I can handle with the current visibility states:

    screen-20230727-105938.1.mp4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions