Skip to content

Commit

Permalink
Add option to keep content visible in PlayerView when player is reset
Browse files Browse the repository at this point in the history
Issue: #2843

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=196349533
  • Loading branch information
ojw28 committed May 12, 2018
1 parent f848d0e commit 1af9334
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 13 deletions.
4 changes: 4 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

* OkHttp extension: Fix to correctly include response headers in thrown
`InvalidResponseCodeException`s.
* UI components:
* Add `PlayerView.setKeepContentOnPlayerReset` to keep the currently displayed
video frame or media artwork visible when the player is reset
([#2843](https://github.com/google/ExoPlayer/issues/2843)).

### 2.8.0 ###

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@
* <li>Corresponding method: {@link #setShutterBackgroundColor(int)}
* <li>Default: {@code unset}
* </ul>
* <li><b>{@code keep_content_on_player_reset}</b> - Whether the currently displayed video frame
* or media artwork is kept visible when the player is reset.
* <ul>
* <li>Corresponding method: {@link #setKeepContentOnPlayerReset(boolean)}
* <li>Default: {@code false}
* </ul>
* <li><b>{@code player_layout_id}</b> - Specifies the id of the layout to be inflated. See below
* for more details.
* <ul>
Expand Down Expand Up @@ -242,6 +248,7 @@ public class PlayerView extends FrameLayout {
private boolean useArtwork;
private Bitmap defaultArtwork;
private boolean showBuffering;
private boolean keepContentOnPlayerReset;
private @Nullable ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider;
private @Nullable CharSequence customErrorMessage;
private int controllerShowTimeoutMs;
Expand Down Expand Up @@ -313,6 +320,9 @@ public PlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
a.getBoolean(R.styleable.PlayerView_hide_on_touch, controllerHideOnTouch);
controllerAutoShow = a.getBoolean(R.styleable.PlayerView_auto_show, controllerAutoShow);
showBuffering = a.getBoolean(R.styleable.PlayerView_show_buffering, showBuffering);
keepContentOnPlayerReset =
a.getBoolean(
R.styleable.PlayerView_keep_content_on_player_reset, keepContentOnPlayerReset);
controllerHideDuringAds =
a.getBoolean(R.styleable.PlayerView_hide_during_ads, controllerHideDuringAds);
} finally {
Expand Down Expand Up @@ -472,14 +482,12 @@ public void setPlayer(Player player) {
if (useController) {
controller.setPlayer(player);
}
if (shutterView != null) {
shutterView.setVisibility(VISIBLE);
}
if (subtitleView != null) {
subtitleView.setCues(null);
}
updateBuffering();
updateErrorMessage();
updateForCurrentTrackSelections(/* isNewPlayer= */ true);
if (player != null) {
Player.VideoComponent newVideoComponent = player.getVideoComponent();
if (newVideoComponent != null) {
Expand All @@ -496,10 +504,8 @@ public void setPlayer(Player player) {
}
player.addListener(componentListener);
maybeShowController(false);
updateForCurrentTrackSelections();
} else {
hideController();
hideArtwork();
}
}

Expand Down Expand Up @@ -542,7 +548,7 @@ public void setUseArtwork(boolean useArtwork) {
Assertions.checkState(!useArtwork || artworkView != null);
if (this.useArtwork != useArtwork) {
this.useArtwork = useArtwork;
updateForCurrentTrackSelections();
updateForCurrentTrackSelections(/* isNewPlayer= */ false);
}
}

Expand All @@ -560,7 +566,7 @@ public Bitmap getDefaultArtwork() {
public void setDefaultArtwork(Bitmap defaultArtwork) {
if (this.defaultArtwork != defaultArtwork) {
this.defaultArtwork = defaultArtwork;
updateForCurrentTrackSelections();
updateForCurrentTrackSelections(/* isNewPlayer= */ false);
}
}

Expand Down Expand Up @@ -600,6 +606,32 @@ public void setShutterBackgroundColor(int color) {
}
}

/**
* Sets whether the currently displayed video frame or media artwork is kept visible when the
* player is reset. A player reset is defined to mean the player being re-prepared with different
* media, {@link Player#stop(boolean)} being called with {@code reset=true}, or the player being
* replaced or cleared by calling {@link #setPlayer(Player)}.
*
* <p>If enabled, the currently displayed video frame or media artwork will be kept visible until
* the player set on the view has been successfully prepared with new media and loaded enough of
* it to have determined the available tracks. Hence enabling this option allows transitioning
* from playing one piece of media to another, or from using one player instance to another,
* without clearing the view's content.
*
* <p>If disabled, the currently displayed video frame or media artwork will be hidden as soon as
* the player is reset. Note that the video frame is hidden by making {@code exo_shutter} visible.
* Hence the video frame will not be hidden if using a custom layout that omits this view.
*
* @param keepContentOnPlayerReset Whether the currently displayed video frame or media artwork is
* kept visible when the player is reset.
*/
public void setKeepContentOnPlayerReset(boolean keepContentOnPlayerReset) {
if (this.keepContentOnPlayerReset != keepContentOnPlayerReset) {
this.keepContentOnPlayerReset = keepContentOnPlayerReset;
updateForCurrentTrackSelections(/* isNewPlayer= */ false);
}
}

/**
* Sets whether a buffering spinner is displayed when the player is in the buffering state. The
* buffering spinner is not displayed by default.
Expand Down Expand Up @@ -961,10 +993,20 @@ private boolean isPlayingAd() {
return player != null && player.isPlayingAd() && player.getPlayWhenReady();
}

private void updateForCurrentTrackSelections() {
if (player == null) {
private void updateForCurrentTrackSelections(boolean isNewPlayer) {
if (player == null || player.getCurrentTrackGroups().isEmpty()) {
if (!keepContentOnPlayerReset) {
hideArtwork();
closeShutter();
}
return;
}

if (isNewPlayer && !keepContentOnPlayerReset) {
// Hide any video from the previous player.
closeShutter();
}

TrackSelectionArray selections = player.getCurrentTrackSelections();
for (int i = 0; i < selections.length; i++) {
if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) {
Expand All @@ -974,10 +1016,9 @@ private void updateForCurrentTrackSelections() {
return;
}
}

// Video disabled so the shutter must be closed.
if (shutterView != null) {
shutterView.setVisibility(VISIBLE);
}
closeShutter();
// Display artwork if enabled and available, else hide it.
if (useArtwork) {
for (int i = 0; i < selections.length; i++) {
Expand Down Expand Up @@ -1034,6 +1075,12 @@ private void hideArtwork() {
}
}

private void closeShutter() {
if (shutterView != null) {
shutterView.setVisibility(View.VISIBLE);
}
}

private void updateBuffering() {
if (bufferingView != null) {
boolean showBufferingSpinner =
Expand Down Expand Up @@ -1177,7 +1224,7 @@ public void onRenderedFirstFrame() {

@Override
public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selections) {
updateForCurrentTrackSelections();
updateForCurrentTrackSelections(/* isNewPlayer= */ false);
}

// Player.EventListener implementation
Expand Down
1 change: 1 addition & 0 deletions library/ui/src/main/res/values/attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<attr name="hide_during_ads" format="boolean"/>
<attr name="auto_show" format="boolean"/>
<attr name="show_buffering" format="boolean"/>
<attr name="keep_content_on_player_reset" format="boolean"/>
<attr name="resize_mode"/>
<attr name="surface_type"/>
<attr name="player_layout_id"/>
Expand Down

0 comments on commit 1af9334

Please sign in to comment.