diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b0544c1d1b..ed9635a340 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -15,8 +15,11 @@ for the underlying track was changing (e.g., at some period transitions). * Add `SilenceMediaSource` that can be used to play silence of a given duration ([#5735](https://github.com/google/ExoPlayer/issues/5735)). -* UI: Change playback controls toggle from touch down to touch up events - ([#5784](https://github.com/google/ExoPlayer/issues/5784)). +* UI: + * Allow setting `DefaultTimeBar` attributes on `PlayerView` and + `PlayerControlView`. + * Change playback controls toggle from touch down to touch up events + ([#5784](https://github.com/google/ExoPlayer/issues/5784)). * Add a workaround for broken raw audio decoding on Oppo R9 ([#5782](https://github.com/google/ExoPlayer/issues/5782)). * Offline: Add Scheduler implementation which uses WorkManager. diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java index 328b5d6a49..5c70203788 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/DefaultTimeBar.java @@ -220,11 +220,26 @@ public class DefaultTimeBar extends View implements TimeBar { private @Nullable long[] adGroupTimesMs; private @Nullable boolean[] playedAdGroups; - /** Creates a new time bar. */ + public DefaultTimeBar(Context context) { + this(context, null); + } + + public DefaultTimeBar(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public DefaultTimeBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, attrs); + } + // Suppress warnings due to usage of View methods in the constructor. @SuppressWarnings("nullness:method.invocation.invalid") - public DefaultTimeBar(Context context, AttributeSet attrs) { - super(context, attrs); + public DefaultTimeBar( + Context context, + @Nullable AttributeSet attrs, + int defStyleAttr, + @Nullable AttributeSet timebarAttrs) { + super(context, attrs, defStyleAttr); seekBounds = new Rect(); progressBar = new Rect(); bufferedBar = new Rect(); @@ -251,9 +266,9 @@ public class DefaultTimeBar extends View implements TimeBar { int defaultScrubberEnabledSize = dpToPx(density, DEFAULT_SCRUBBER_ENABLED_SIZE_DP); int defaultScrubberDisabledSize = dpToPx(density, DEFAULT_SCRUBBER_DISABLED_SIZE_DP); int defaultScrubberDraggedSize = dpToPx(density, DEFAULT_SCRUBBER_DRAGGED_SIZE_DP); - if (attrs != null) { - TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DefaultTimeBar, 0, - 0); + if (timebarAttrs != null) { + TypedArray a = + context.getTheme().obtainStyledAttributes(timebarAttrs, R.styleable.DefaultTimeBar, 0, 0); try { scrubberDrawable = a.getDrawable(R.styleable.DefaultTimeBar_scrubber_drawable); if (scrubberDrawable != null) { diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java index 54a592ce6f..b9b2456722 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerControlView.java @@ -28,6 +28,7 @@ import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -97,6 +98,9 @@ import java.util.Locale; *
  • Corresponding method: None *
  • Default: {@code R.layout.exo_player_control_view} * + *
  • All attributes that can be set on {@link DefaultTimeBar} can also be set on a + * PlayerControlView, and will be propagated to the inflated {@link DefaultTimeBar} unless the + * layout is overridden to specify a custom {@code exo_progress} (see below). * * *

    Overriding the layout file

    @@ -154,7 +158,15 @@ import java.util.Locale; * + *
  • {@code exo_progress_placeholder} - A placeholder that's replaced with the inflated + * {@link DefaultTimeBar}. Ignored if an {@code exo_progress} view exists. + * *
  • {@code exo_progress} - Time bar that's updated during playback and allows seeking. + * {@link DefaultTimeBar} attributes set on the PlayerControlView will not be automatically + * propagated through to this instance. If a view exists with this id, any {@code + * exo_progress_placeholder} view will be ignored. * @@ -330,9 +342,27 @@ public class PlayerControlView extends FrameLayout { LayoutInflater.from(context).inflate(controllerLayoutId, this); setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + TimeBar customTimeBar = findViewById(R.id.exo_progress); + View timeBarPlaceholder = findViewById(R.id.exo_progress_placeholder); + if (customTimeBar != null) { + timeBar = customTimeBar; + } else if (timeBarPlaceholder != null) { + // Propagate attrs as timebarAttrs so that DefaultTimeBar's custom attributes are transferred, + // but standard attributes (e.g. background) are not. + DefaultTimeBar defaultTimeBar = new DefaultTimeBar(context, null, 0, playbackAttrs); + defaultTimeBar.setId(R.id.exo_progress); + defaultTimeBar.setLayoutParams(timeBarPlaceholder.getLayoutParams()); + ViewGroup parent = ((ViewGroup) timeBarPlaceholder.getParent()); + int timeBarIndex = parent.indexOfChild(timeBarPlaceholder); + parent.removeView(timeBarPlaceholder); + parent.addView(defaultTimeBar, timeBarIndex); + timeBar = defaultTimeBar; + } else { + timeBar = null; + } durationView = findViewById(R.id.exo_duration); positionView = findViewById(R.id.exo_position); - timeBar = findViewById(R.id.exo_progress); + if (timeBar != null) { timeBar.addListener(componentListener); } diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java index 21467c3e25..5bb8324780 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java @@ -162,9 +162,10 @@ import java.util.List; *
  • Corresponding method: None *
  • Default: {@code R.layout.exo_player_control_view} * - *
  • All attributes that can be set on a {@link PlayerControlView} can also be set on a - * PlayerView, and will be propagated to the inflated {@link PlayerControlView} unless the - * layout is overridden to specify a custom {@code exo_controller} (see below). + *
  • All attributes that can be set on {@link PlayerControlView} and {@link DefaultTimeBar} can + * also be set on a PlayerView, and will be propagated to the inflated {@link + * PlayerControlView} unless the layout is overridden to specify a custom {@code + * exo_controller} (see below). * * *

    Overriding the layout file

    @@ -214,9 +215,10 @@ import java.util.List; *
  • Type: {@link View} * *
  • {@code exo_controller} - An already inflated {@link PlayerControlView}. Allows use - * of a custom extension of {@link PlayerControlView}. 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 PlayerControlView}. {@link PlayerControlView} and {@link + * DefaultTimeBar} attributes set on the PlayerView 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. * @@ -456,8 +458,9 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider this.controller = customController; } else if (controllerPlaceholder != null) { // Propagate attrs as playbackAttrs so that PlayerControlView's custom attributes are - // transferred, but standard FrameLayout attributes (e.g. background) are not. + // transferred, but standard attributes (e.g. background) are not. this.controller = new PlayerControlView(context, null, 0, attrs); + controller.setId(R.id.exo_controller); controller.setLayoutParams(controllerPlaceholder.getLayoutParams()); ViewGroup parent = ((ViewGroup) controllerPlaceholder.getParent()); int controllerIndex = parent.indexOfChild(controllerPlaceholder); diff --git a/library/ui/src/main/res/layout/exo_playback_control_view.xml b/library/ui/src/main/res/layout/exo_playback_control_view.xml index ed2fb8e2b2..027e57ee92 100644 --- a/library/ui/src/main/res/layout/exo_playback_control_view.xml +++ b/library/ui/src/main/res/layout/exo_playback_control_view.xml @@ -76,8 +76,7 @@ android:includeFontPadding="false" android:textColor="#FFBEBEBE"/> - diff --git a/library/ui/src/main/res/values/attrs.xml b/library/ui/src/main/res/values/attrs.xml index 27e6a5b3b8..706fba0e0b 100644 --- a/library/ui/src/main/res/values/attrs.xml +++ b/library/ui/src/main/res/values/attrs.xml @@ -31,18 +31,36 @@ - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -58,9 +76,11 @@ - + + - + + @@ -69,6 +89,20 @@ + + + + + + + + + + + + + + @@ -83,22 +117,36 @@ + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/library/ui/src/main/res/values/ids.xml b/library/ui/src/main/res/values/ids.xml index e57301f946..17b55cd731 100644 --- a/library/ui/src/main/res/values/ids.xml +++ b/library/ui/src/main/res/values/ids.xml @@ -33,6 +33,7 @@ +