Commit 2accb41e by olly Committed by Ian Baker

StyledPlayerControlView: Fixes for minimal mode

- Re-layer layout so that the central controls end up on
  top (and, more importantly, have preference for receiving
  touch input) if the view is so small that elements start
  to overlap. This requires splitting the background and
  the controls themselves.
- Fix bug that could cause the scrubber to not be hidden
  in minimal mode, if the mode is entered when the controls
  are not visible.
- Fix positioning of minimal controls.
- Remove scrubber padding in minimal mode, since the scrubber
- Remove unused bar_gravity value.

PiperOrigin-RevId: 347008789
parent 7d478a9f
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
* Add option to specify multiple preferred audio or text languages. * Add option to specify multiple preferred audio or text languages.
* Forward `Timeline` and `MediaPeriodId` to `TrackSelection.Factory`. * Forward `Timeline` and `MediaPeriodId` to `TrackSelection.Factory`.
* UI: * UI:
* Miscellaneous fixes for `StyledPlayerControlView` in minimal mode.
* Show overflow button in `StyledPlayerControlView` only when there is not * Show overflow button in `StyledPlayerControlView` only when there is not
enough space. enough space.
* Update StyledPlayer's control overlay scrim from 30% opacity to 60% * Update StyledPlayer's control overlay scrim from 30% opacity to 60%
......
...@@ -157,8 +157,6 @@ public class DefaultTimeBar extends View implements TimeBar { ...@@ -157,8 +157,6 @@ public class DefaultTimeBar extends View implements TimeBar {
public static final int BAR_GRAVITY_CENTER = 0; public static final int BAR_GRAVITY_CENTER = 0;
/** Vertical gravity for progress bar to be located at the bottom in the view. */ /** Vertical gravity for progress bar to be located at the bottom in the view. */
public static final int BAR_GRAVITY_BOTTOM = 1; public static final int BAR_GRAVITY_BOTTOM = 1;
/** Vertical gravity for progress bar to be located at the top in the view. */
public static final int BAR_GRAVITY_TOP = 2;
// LINT.ThenChange(../../../../../../../../../ui/src/main/res/values/attrs.xml) // LINT.ThenChange(../../../../../../../../../ui/src/main/res/values/attrs.xml)
/** The threshold in dps above the bar at which touch events trigger fine scrub mode. */ /** The threshold in dps above the bar at which touch events trigger fine scrub mode. */
...@@ -216,6 +214,7 @@ public class DefaultTimeBar extends View implements TimeBar { ...@@ -216,6 +214,7 @@ public class DefaultTimeBar extends View implements TimeBar {
private ValueAnimator scrubberScalingAnimator; private ValueAnimator scrubberScalingAnimator;
private float scrubberScale; private float scrubberScale;
private boolean scrubberPaddingDisabled;
private boolean scrubbing; private boolean scrubbing;
private long scrubPosition; private long scrubPosition;
private long duration; private long duration;
...@@ -370,7 +369,12 @@ public class DefaultTimeBar extends View implements TimeBar { ...@@ -370,7 +369,12 @@ public class DefaultTimeBar extends View implements TimeBar {
/** Shows the scrubber handle. */ /** Shows the scrubber handle. */
public void showScrubber() { public void showScrubber() {
showScrubber(/* showAnimationDurationMs= */ 0); if (scrubberScalingAnimator.isStarted()) {
scrubberScalingAnimator.cancel();
}
scrubberPaddingDisabled = false;
scrubberScale = 1;
invalidate(seekBounds);
} }
/** /**
...@@ -382,14 +386,20 @@ public class DefaultTimeBar extends View implements TimeBar { ...@@ -382,14 +386,20 @@ public class DefaultTimeBar extends View implements TimeBar {
if (scrubberScalingAnimator.isStarted()) { if (scrubberScalingAnimator.isStarted()) {
scrubberScalingAnimator.cancel(); scrubberScalingAnimator.cancel();
} }
scrubberPaddingDisabled = false;
scrubberScalingAnimator.setFloatValues(scrubberScale, SHOWN_SCRUBBER_SCALE); scrubberScalingAnimator.setFloatValues(scrubberScale, SHOWN_SCRUBBER_SCALE);
scrubberScalingAnimator.setDuration(showAnimationDurationMs); scrubberScalingAnimator.setDuration(showAnimationDurationMs);
scrubberScalingAnimator.start(); scrubberScalingAnimator.start();
} }
/** Hides the scrubber handle. */ /** Hides the scrubber handle. */
public void hideScrubber() { public void hideScrubber(boolean disableScrubberPadding) {
hideScrubber(/* hideAnimationDurationMs= */ 0); if (scrubberScalingAnimator.isStarted()) {
scrubberScalingAnimator.cancel();
}
scrubberPaddingDisabled = disableScrubberPadding;
scrubberScale = 0;
invalidate(seekBounds);
} }
/** /**
...@@ -668,20 +678,25 @@ public class DefaultTimeBar extends View implements TimeBar { ...@@ -668,20 +678,25 @@ public class DefaultTimeBar extends View implements TimeBar {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int width = right - left; int width = right - left;
int height = bottom - top; int height = bottom - top;
int barY = (height - touchTargetHeight) / 2;
int seekLeft = getPaddingLeft(); int seekLeft = getPaddingLeft();
int seekRight = width - getPaddingRight(); int seekRight = width - getPaddingRight();
int progressY; int seekBoundsY;
int progressBarY;
int scrubberPadding = scrubberPaddingDisabled ? 0 : this.scrubberPadding;
if (barGravity == BAR_GRAVITY_BOTTOM) { if (barGravity == BAR_GRAVITY_BOTTOM) {
progressY = barY + touchTargetHeight - (getPaddingBottom() + scrubberPadding + barHeight / 2); seekBoundsY = height - getPaddingBottom() - touchTargetHeight;
} else if (barGravity == BAR_GRAVITY_TOP) { progressBarY =
progressY = barY + getPaddingTop() + scrubberPadding - barHeight / 2; height - getPaddingBottom() - barHeight - Math.max(scrubberPadding - (barHeight / 2), 0);
} else { } else {
progressY = barY + (touchTargetHeight - barHeight) / 2; seekBoundsY = (height - touchTargetHeight) / 2;
} progressBarY = (height - barHeight) / 2;
seekBounds.set(seekLeft, barY, seekRight, barY + touchTargetHeight); }
progressBar.set(seekBounds.left + scrubberPadding, progressY, seekBounds.set(seekLeft, seekBoundsY, seekRight, seekBoundsY + touchTargetHeight);
seekBounds.right - scrubberPadding, progressY + barHeight); progressBar.set(
seekBounds.left + scrubberPadding,
progressBarY,
seekBounds.right - scrubberPadding,
progressBarY + barHeight);
if (Util.SDK_INT >= 29) { if (Util.SDK_INT >= 29) {
setSystemGestureExclusionRectsV29(width, height); setSystemGestureExclusionRectsV29(width, height);
} }
......
...@@ -98,7 +98,7 @@ import java.util.List; ...@@ -98,7 +98,7 @@ import java.util.List;
shownButtons = new ArrayList<>(); shownButtons = new ArrayList<>();
// Relating to Center View // Relating to Center View
ViewGroup centerView = styledPlayerControlView.findViewById(R.id.exo_center_view); View controlsBackground = styledPlayerControlView.findViewById(R.id.exo_controls_background);
centerControls = styledPlayerControlView.findViewById(R.id.exo_center_controls); centerControls = styledPlayerControlView.findViewById(R.id.exo_center_controls);
// Relating to Minimal Layout // Relating to Minimal Layout
...@@ -137,8 +137,11 @@ import java.util.List; ...@@ -137,8 +137,11 @@ import java.util.List;
fadeOutAnimator.addUpdateListener( fadeOutAnimator.addUpdateListener(
animation -> { animation -> {
float animatedValue = (float) animation.getAnimatedValue(); float animatedValue = (float) animation.getAnimatedValue();
if (centerView != null) { if (controlsBackground != null) {
centerView.setAlpha(animatedValue); controlsBackground.setAlpha(animatedValue);
}
if (centerControls != null) {
centerControls.setAlpha(animatedValue);
} }
if (minimalControls != null) { if (minimalControls != null) {
minimalControls.setAlpha(animatedValue); minimalControls.setAlpha(animatedValue);
...@@ -155,8 +158,11 @@ import java.util.List; ...@@ -155,8 +158,11 @@ import java.util.List;
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
if (centerView != null) { if (controlsBackground != null) {
centerView.setVisibility(View.INVISIBLE); controlsBackground.setVisibility(View.INVISIBLE);
}
if (centerControls != null) {
centerControls.setVisibility(View.INVISIBLE);
} }
if (minimalControls != null) { if (minimalControls != null) {
minimalControls.setVisibility(View.INVISIBLE); minimalControls.setVisibility(View.INVISIBLE);
...@@ -169,8 +175,11 @@ import java.util.List; ...@@ -169,8 +175,11 @@ import java.util.List;
fadeInAnimator.addUpdateListener( fadeInAnimator.addUpdateListener(
animation -> { animation -> {
float animatedValue = (float) animation.getAnimatedValue(); float animatedValue = (float) animation.getAnimatedValue();
if (centerView != null) { if (controlsBackground != null) {
centerView.setAlpha(animatedValue); controlsBackground.setAlpha(animatedValue);
}
if (centerControls != null) {
centerControls.setAlpha(animatedValue);
} }
if (minimalControls != null) { if (minimalControls != null) {
minimalControls.setAlpha(animatedValue); minimalControls.setAlpha(animatedValue);
...@@ -180,8 +189,11 @@ import java.util.List; ...@@ -180,8 +189,11 @@ import java.util.List;
new AnimatorListenerAdapter() { new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationStart(Animator animation) { public void onAnimationStart(Animator animation) {
if (centerView != null) { if (controlsBackground != null) {
centerView.setVisibility(View.VISIBLE); controlsBackground.setVisibility(View.VISIBLE);
}
if (centerControls != null) {
centerControls.setVisibility(View.VISIBLE);
} }
if (minimalControls != null) { if (minimalControls != null) {
minimalControls.setVisibility(isMinimalMode ? View.VISIBLE : View.INVISIBLE); minimalControls.setVisibility(isMinimalMode ? View.VISIBLE : View.INVISIBLE);
...@@ -595,13 +607,14 @@ import java.util.List; ...@@ -595,13 +607,14 @@ import java.util.List;
.getDimensionPixelSize(R.dimen.exo_styled_progress_margin_bottom); .getDimensionPixelSize(R.dimen.exo_styled_progress_margin_bottom);
timeBarParams.bottomMargin = (isMinimalMode ? 0 : timeBarMarginBottom); timeBarParams.bottomMargin = (isMinimalMode ? 0 : timeBarMarginBottom);
timeBar.setLayoutParams(timeBarParams); timeBar.setLayoutParams(timeBarParams);
if (timeBar instanceof DefaultTimeBar if (timeBar instanceof DefaultTimeBar) {
&& uxState != UX_STATE_ANIMATING_HIDE DefaultTimeBar defaultTimeBar = (DefaultTimeBar) timeBar;
&& uxState != UX_STATE_ANIMATING_SHOW) { if (isMinimalMode) {
if (isMinimalMode || uxState != UX_STATE_ALL_VISIBLE) { defaultTimeBar.hideScrubber(/* disableScrubberPadding= */ true);
((DefaultTimeBar) timeBar).hideScrubber(); } else if (uxState == UX_STATE_ONLY_PROGRESS_VISIBLE) {
} else { defaultTimeBar.hideScrubber(/* disableScrubberPadding= */ false);
((DefaultTimeBar) timeBar).showScrubber(); } else if (uxState != UX_STATE_ANIMATING_HIDE && uxState != UX_STATE_ANIMATING_SHOW) {
defaultTimeBar.showScrubber();
} }
} }
} }
......
...@@ -15,43 +15,12 @@ ...@@ -15,43 +15,12 @@
--> -->
<merge xmlns:android="http://schemas.android.com/apk/res/android"> <merge xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout android:id="@+id/exo_center_view" <View android:id="@+id/exo_controls_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layoutDirection="ltr">
<View android:id="@+id/exo_center_view_background"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center" android:layout_gravity="center"
android:background="@color/exo_black_opacity_60"/> android:background="@color/exo_black_opacity_60"/>
<LinearLayout android:id="@+id/exo_center_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center">
<ImageButton android:id="@+id/exo_prev"
style="@style/ExoStyledControls.Button.Center.Previous"/>
<Button android:id="@+id/exo_rew_with_amount"
style="@style/ExoStyledControls.Button.Center.RewWithAmount"/>
<ImageButton android:id="@+id/exo_play_pause"
style="@style/ExoStyledControls.Button.Center.PlayPause"/>
<Button android:id="@+id/exo_ffwd_with_amount"
style="@style/ExoStyledControls.Button.Center.FfwdWithAmount"/>
<ImageButton android:id="@+id/exo_next"
style="@style/ExoStyledControls.Button.Center.Next"/>
</LinearLayout>
</FrameLayout>
<FrameLayout android:id="@+id/exo_bottom_bar" <FrameLayout android:id="@+id/exo_bottom_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/exo_styled_bottom_bar_height" android:layout_height="@dimen/exo_styled_bottom_bar_height"
...@@ -84,7 +53,6 @@ ...@@ -84,7 +53,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end" android:layout_gravity="center_vertical|end"
android:orientation="horizontal"
android:layoutDirection="ltr"> android:layoutDirection="ltr">
<ImageButton android:id="@+id/exo_shuffle" <ImageButton android:id="@+id/exo_shuffle"
...@@ -130,18 +98,42 @@ ...@@ -130,18 +98,42 @@
</FrameLayout> </FrameLayout>
<LinearLayout android:id="@+id/exo_minimal_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="bottom|end"
android:layout_marginBottom="@dimen/exo_styled_progress_layout_height"
android:visibility="invisible"/>
<View android:id="@+id/exo_progress_placeholder" <View android:id="@+id/exo_progress_placeholder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/exo_styled_progress_layout_height" android:layout_height="@dimen/exo_styled_progress_layout_height"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:layout_marginBottom="@dimen/exo_styled_progress_margin_bottom"/> android:layout_marginBottom="@dimen/exo_styled_progress_margin_bottom"/>
<LinearLayout android:id="@+id/exo_minimal_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="@dimen/exo_styled_minimal_controls_margin_bottom"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layoutDirection="ltr"/>
<LinearLayout android:id="@+id/exo_center_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center">
<ImageButton android:id="@+id/exo_prev"
style="@style/ExoStyledControls.Button.Center.Previous"/>
<Button android:id="@+id/exo_rew_with_amount"
style="@style/ExoStyledControls.Button.Center.RewWithAmount"/>
<ImageButton android:id="@+id/exo_play_pause"
style="@style/ExoStyledControls.Button.Center.PlayPause"/>
<Button android:id="@+id/exo_ffwd_with_amount"
style="@style/ExoStyledControls.Button.Center.FfwdWithAmount"/>
<ImageButton android:id="@+id/exo_next"
style="@style/ExoStyledControls.Button.Center.Next"/>
</LinearLayout>
</merge> </merge>
...@@ -80,7 +80,6 @@ ...@@ -80,7 +80,6 @@
<attr name="bar_gravity" format="enum"> <attr name="bar_gravity" format="enum">
<enum name="center" value="0"/> <enum name="center" value="0"/>
<enum name="bottom" value="1"/> <enum name="bottom" value="1"/>
<enum name="top" value="2"/>
</attr> </attr>
<attr name="touch_target_height" format="dimension"/> <attr name="touch_target_height" format="dimension"/>
<attr name="ad_marker_width" format="dimension"/> <attr name="ad_marker_width" format="dimension"/>
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
<dimen name="exo_styled_progress_margin_bottom">52dp</dimen> <dimen name="exo_styled_progress_margin_bottom">52dp</dimen>
<dimen name="exo_styled_bottom_bar_height">60dp</dimen> <dimen name="exo_styled_bottom_bar_height">60dp</dimen>
<dimen name="exo_styled_time_padding">10dp</dimen> <dimen name="exo_styled_time_padding">10dp</dimen>
<dimen name="exo_styled_minimal_controls_margin_bottom">4dp</dimen>
<dimen name="exo_error_message_height">32dp</dimen> <dimen name="exo_error_message_height">32dp</dimen>
<dimen name="exo_error_message_margin_bottom">64dp</dimen> <dimen name="exo_error_message_margin_bottom">64dp</dimen>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment