diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 0caad888d9..a464b7e826 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -45,6 +45,8 @@
* Skip ads before the ad preceding the player's initial seek position
([#3527](https://github.com/google/ExoPlayer/issues/3527)).
* Fix ad loading when there is no preroll.
+ * Add an option to turn off hiding controls during ad playback
+ ([#3532](https://github.com/google/ExoPlayer/issues/3532)).
### 2.6.0 ###
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
index dcc1c62569..1f67b83ba0 100644
--- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/SimpleExoPlayerView.java
@@ -56,146 +56,144 @@ import java.util.List;
/**
* A high level view for {@link SimpleExoPlayer} media playbacks. It displays video, subtitles and
* album art during playback, and displays playback controls using a {@link PlaybackControlView}.
- *
- * A SimpleExoPlayerView can be customized by setting attributes (or calling corresponding methods),
- * overriding the view's layout file or by specifying a custom view layout file, as outlined below.
+ *
+ *
A SimpleExoPlayerView can be customized by setting attributes (or calling corresponding
+ * methods), overriding the view's layout file or by specifying a custom view layout file, as
+ * outlined below.
*
*
Attributes
+ *
* The following attributes can be set on a SimpleExoPlayerView when used in a layout XML file:
+ *
*
+ *
*
* - {@code use_artwork} - Whether artwork is used if available in audio streams.
*
- * - Corresponding method: {@link #setUseArtwork(boolean)}
- * - Default: {@code true}
+ * - Corresponding method: {@link #setUseArtwork(boolean)}
+ *
- Default: {@code true}
*
- *
* - {@code default_artwork} - Default artwork to use if no artwork available in audio
* streams.
*
- * - Corresponding method: {@link #setDefaultArtwork(Bitmap)}
- * - Default: {@code null}
+ * - Corresponding method: {@link #setDefaultArtwork(Bitmap)}
+ *
- Default: {@code null}
*
- *
* - {@code use_controller} - Whether the playback controls can be shown.
*
- * - Corresponding method: {@link #setUseController(boolean)}
- * - Default: {@code true}
+ * - Corresponding method: {@link #setUseController(boolean)}
+ *
- Default: {@code true}
*
- *
* - {@code hide_on_touch} - Whether the playback controls are hidden by touch events.
*
- * - Corresponding method: {@link #setControllerHideOnTouch(boolean)}
- * - Default: {@code true}
+ * - Corresponding method: {@link #setControllerHideOnTouch(boolean)}
+ *
- Default: {@code true}
*
- *
* - {@code auto_show} - Whether the playback controls are automatically shown when
* playback starts, pauses, ends, or fails. If set to false, the playback controls can be
* manually operated with {@link #showController()} and {@link #hideController()}.
*
- * - Corresponding method: {@link #setControllerAutoShow(boolean)}
- * - Default: {@code true}
+ * - Corresponding method: {@link #setControllerAutoShow(boolean)}
+ *
- Default: {@code true}
+ *
+ * - {@code hide_during_ads} - Whether the playback controls are hidden during ads.
+ * Controls are always shown during ads if they are enabled and the player is paused.
+ *
+ * - Corresponding method: {@link #setControllerHideDuringAds(boolean)}
+ *
- Default: {@code true}
*
- *
* - {@code resize_mode} - Controls how video and album art is resized within the view.
* Valid values are {@code fit}, {@code fixed_width}, {@code fixed_height} and {@code fill}.
*
- * - Corresponding method: {@link #setResizeMode(int)}
- * - Default: {@code fit}
+ * - Corresponding method: {@link #setResizeMode(int)}
+ *
- Default: {@code fit}
*
- *
* - {@code surface_type} - The type of surface view used for video playbacks. Valid
* values are {@code surface_view}, {@code texture_view} and {@code none}. Using {@code none}
* is recommended for audio only applications, since creating the surface can be expensive.
* Using {@code surface_view} is recommended for video applications.
*
- * - Corresponding method: None
- * - Default: {@code surface_view}
+ * - Corresponding method: None
+ *
- Default: {@code surface_view}
*
- *
* - {@code shutter_background_color} - The background color of the {@code exo_shutter}
* view.
*
- * - Corresponding method: {@link #setShutterBackgroundColor(int)}
- * - Default: {@code unset}
+ * - Corresponding method: {@link #setShutterBackgroundColor(int)}
+ *
- Default: {@code unset}
*
- *
* - {@code player_layout_id} - Specifies the id of the layout to be inflated. See below
* for more details.
*
- * - Corresponding method: None
- * - Default: {@code R.id.exo_simple_player_view}
+ * - Corresponding method: None
+ *
- Default: {@code R.id.exo_simple_player_view}
*
* - {@code controller_layout_id} - Specifies the id of the layout resource to be
* inflated by the child {@link PlaybackControlView}. See below for more details.
*
- * - Corresponding method: None
- * - Default: {@code R.id.exo_playback_control_view}
+ * - Corresponding method: None
+ *
- Default: {@code R.id.exo_playback_control_view}
*
* - All attributes that can be set on a {@link PlaybackControlView} can also be set on a
* SimpleExoPlayerView, and will be propagated to the inflated {@link PlaybackControlView}
* unless the layout is overridden to specify a custom {@code exo_controller} (see below).
- *
*
*
* Overriding the layout file
+ *
* To customize the layout of SimpleExoPlayerView throughout your app, or just for certain
* configurations, you can define {@code exo_simple_player_view.xml} layout files in your
* application {@code res/layout*} directories. These layouts will override the one provided by the
* ExoPlayer library, and will be inflated for use by SimpleExoPlayerView. The view identifies and
* binds its children by looking for the following ids:
+ *
*
+ *
*
* - {@code exo_content_frame} - A frame whose aspect ratio is resized based on the video
* or album art of the media being played, and the configured {@code resize_mode}. The video
* surface view is inflated into this frame as its first child.
*
- * - Type: {@link AspectRatioFrameLayout}
+ * - Type: {@link AspectRatioFrameLayout}
*
- *
* - {@code exo_shutter} - A view that's made visible when video should be hidden. This
* view is typically an opaque view that covers the video surface view, thereby obscuring it
* when visible.
*
- * - Type: {@link View}
+ * - Type: {@link View}
*
- *
* - {@code exo_subtitles} - Displays subtitles.
*
- * - Type: {@link SubtitleView}
+ * - Type: {@link SubtitleView}
*
- *
* - {@code exo_artwork} - Displays album art.
*
- * - Type: {@link ImageView}
+ * - Type: {@link ImageView}
*
- *
* - {@code exo_controller_placeholder} - A placeholder that's replaced with the inflated
* {@link PlaybackControlView}. Ignored if an {@code exo_controller} view exists.
*
- * - Type: {@link View}
+ * - Type: {@link View}
*
- *
* - {@code exo_controller} - An already inflated {@link PlaybackControlView}. Allows use
- * of a custom extension of {@link PlaybackControlView}. Note that attributes such as
- * {@code rewind_increment} will not be automatically propagated through to this instance. If
- * a view exists with this id, any {@code exo_controller_placeholder} view will be ignored.
+ * of a custom extension of {@link PlaybackControlView}. Note that attributes such as {@code
+ * rewind_increment} will not be automatically propagated through to this instance. If a view
+ * exists with this id, any {@code exo_controller_placeholder} view will be ignored.
*
- * - Type: {@link PlaybackControlView}
+ * - Type: {@link PlaybackControlView}
*
- *
* - {@code exo_overlay} - A {@link FrameLayout} positioned on top of the player which
* the app can access via {@link #getOverlayFrameLayout()}, provided for convenience.
*
- * - Type: {@link FrameLayout}
+ * - Type: {@link FrameLayout}
*
- *
*
- *
- * All child views are optional and so can be omitted if not required, however where defined they
+ *
+ *
All child views are optional and so can be omitted if not required, however where defined they
* must be of the expected type.
*
*
Specifying a custom layout file
+ *
* Defining your own {@code exo_simple_player_view.xml} is useful to customize the layout of
* SimpleExoPlayerView throughout your application. It's also possible to customize the layout for a
* single instance in a layout file. This is achieved by setting the {@code player_layout_id}
@@ -224,6 +222,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
private Bitmap defaultArtwork;
private int controllerShowTimeoutMs;
private boolean controllerAutoShow;
+ private boolean controllerHideDuringAds;
private boolean controllerHideOnTouch;
public SimpleExoPlayerView(Context context) {
@@ -267,6 +266,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
int controllerShowTimeoutMs = PlaybackControlView.DEFAULT_SHOW_TIMEOUT_MS;
boolean controllerHideOnTouch = true;
boolean controllerAutoShow = true;
+ boolean controllerHideDuringAds = true;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SimpleExoPlayerView, 0, 0);
@@ -288,6 +288,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
controllerHideOnTouch);
controllerAutoShow = a.getBoolean(R.styleable.SimpleExoPlayerView_auto_show,
controllerAutoShow);
+ controllerHideDuringAds =
+ a.getBoolean(R.styleable.SimpleExoPlayerView_hide_during_ads, controllerHideDuringAds);
} finally {
a.recycle();
}
@@ -358,6 +360,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
this.controllerShowTimeoutMs = controller != null ? controllerShowTimeoutMs : 0;
this.controllerHideOnTouch = controllerHideOnTouch;
this.controllerAutoShow = controllerAutoShow;
+ this.controllerHideDuringAds = controllerHideDuringAds;
this.useController = useController && controller != null;
hideController();
}
@@ -649,6 +652,16 @@ public final class SimpleExoPlayerView extends FrameLayout {
this.controllerAutoShow = controllerAutoShow;
}
+ /**
+ * Sets whether the playback controls are hidden when ads are playing. Controls are always shown
+ * during ads if they are enabled and the player is paused.
+ *
+ * @param controllerHideDuringAds Whether the playback controls are hidden when ads are playing.
+ */
+ public void setControllerHideDuringAds(boolean controllerHideDuringAds) {
+ this.controllerHideDuringAds = controllerHideDuringAds;
+ }
+
/**
* Set the {@link PlaybackControlView.VisibilityListener}.
*
@@ -784,8 +797,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
* Shows the playback controls, but only if forced or shown indefinitely.
*/
private void maybeShowController(boolean isForced) {
- if (isPlayingAd()) {
- // Never show the controller if an ad is currently playing.
+ if (isPlayingAd() && controllerHideDuringAds) {
return;
}
if (useController) {
@@ -956,7 +968,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
- if (isPlayingAd()) {
+ if (isPlayingAd() && controllerHideDuringAds) {
hideController();
} else {
maybeShowController(false);
@@ -965,7 +977,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
@Override
public void onPositionDiscontinuity(@DiscontinuityReason int reason) {
- if (isPlayingAd()) {
+ if (isPlayingAd() && controllerHideDuringAds) {
hideController();
}
}
diff --git a/library/ui/src/main/res/values/attrs.xml b/library/ui/src/main/res/values/attrs.xml
index 525f95768c..1ab3854d21 100644
--- a/library/ui/src/main/res/values/attrs.xml
+++ b/library/ui/src/main/res/values/attrs.xml
@@ -47,6 +47,7 @@
+