diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
index 91308848f9..f83bab5770 100644
--- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java
@@ -84,6 +84,12 @@ import java.util.Locale;
*
Default: {@link PlaybackControlView#DEFAULT_REPEAT_TOGGLE_MODES}
*
*
+ * {@code show_shuffle_button} - Whether the shuffle button is shown.
+ *
+ * - Corresponding method: {@link #setShowShuffleButton(boolean)}
+ * - Default: false
+ *
+ *
* {@code controller_layout_id} - Specifies the id of the layout to be inflated. See
* below for more details.
*
@@ -136,6 +142,11 @@ import java.util.Locale;
* - Type: {@link View}
*
*
+ * {@code exo_shuffle} - The shuffle button.
+ *
+ * - Type: {@link View}
+ *
+ *
* {@code exo_position} - Text view displaying the current playback position.
*
* - Type: {@link TextView}
@@ -221,6 +232,15 @@ public class PlaybackControlView extends FrameLayout {
*/
boolean dispatchSetRepeatMode(Player player, @RepeatMode int repeatMode);
+ /**
+ * Dispatches a {@link Player#setShuffleModeEnabled(boolean)} operation.
+ *
+ * @param player The {@link Player} to which the operation should be dispatched.
+ * @param shuffleModeEnabled Whether shuffling is enabled.
+ * @return True if the operation was dispatched. False if suppressed.
+ */
+ boolean dispatchSetShuffleModeEnabled(Player player, boolean shuffleModeEnabled);
+
}
/**
@@ -247,6 +267,12 @@ public class PlaybackControlView extends FrameLayout {
return true;
}
+ @Override
+ public boolean dispatchSetShuffleModeEnabled(Player player, boolean shuffleModeEnabled) {
+ player.setShuffleModeEnabled(shuffleModeEnabled);
+ return true;
+ }
+
};
/**
@@ -282,6 +308,7 @@ public class PlaybackControlView extends FrameLayout {
private final View fastForwardButton;
private final View rewindButton;
private final ImageView repeatToggleButton;
+ private final View shuffleButton;
private final TextView durationView;
private final TextView positionView;
private final TimeBar timeBar;
@@ -309,6 +336,7 @@ public class PlaybackControlView extends FrameLayout {
private int fastForwardMs;
private int showTimeoutMs;
private @RepeatModeUtil.RepeatToggleModes int repeatToggleModes;
+ private boolean showShuffleButton;
private long hideAtMs;
private long[] adGroupTimesMs;
private boolean[] playedAdGroups;
@@ -345,6 +373,7 @@ public class PlaybackControlView extends FrameLayout {
fastForwardMs = DEFAULT_FAST_FORWARD_MS;
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
+ showShuffleButton = false;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.PlaybackControlView, 0, 0);
@@ -356,6 +385,8 @@ public class PlaybackControlView extends FrameLayout {
controllerLayoutId = a.getResourceId(R.styleable.PlaybackControlView_controller_layout_id,
controllerLayoutId);
repeatToggleModes = getRepeatToggleModes(a, repeatToggleModes);
+ showShuffleButton = a.getBoolean(R.styleable.PlaybackControlView_show_shuffle_button,
+ showShuffleButton);
} finally {
a.recycle();
}
@@ -408,6 +439,10 @@ public class PlaybackControlView extends FrameLayout {
if (repeatToggleButton != null) {
repeatToggleButton.setOnClickListener(componentListener);
}
+ shuffleButton = findViewById(R.id.exo_shuffle);
+ if (shuffleButton != null) {
+ shuffleButton.setOnClickListener(componentListener);
+ }
Resources resources = context.getResources();
repeatOffButtonDrawable = resources.getDrawable(R.drawable.exo_controls_repeat_off);
repeatOneButtonDrawable = resources.getDrawable(R.drawable.exo_controls_repeat_one);
@@ -584,6 +619,23 @@ public class PlaybackControlView extends FrameLayout {
}
}
+ /**
+ * Returns whether the shuffle button is shown.
+ */
+ public boolean getShowShuffleButton() {
+ return showShuffleButton;
+ }
+
+ /**
+ * Sets whether the shuffle button is shown.
+ *
+ * @param showShuffleButton Whether the shuffle button is shown.
+ */
+ public void setShowShuffleButton(boolean showShuffleButton) {
+ this.showShuffleButton = showShuffleButton;
+ updateShuffleButton();
+ }
+
/**
* Shows the playback controls. If {@link #getShowTimeoutMs()} is positive then the controls will
* be automatically hidden after this duration of time has elapsed without user input.
@@ -639,6 +691,7 @@ public class PlaybackControlView extends FrameLayout {
updatePlayPauseButton();
updateNavigation();
updateRepeatModeButton();
+ updateShuffleButton();
updateProgress();
}
@@ -721,6 +774,21 @@ public class PlaybackControlView extends FrameLayout {
repeatToggleButton.setVisibility(View.VISIBLE);
}
+ private void updateShuffleButton() {
+ if (!isVisible() || !isAttachedToWindow || shuffleButton == null) {
+ return;
+ }
+ if (!showShuffleButton) {
+ shuffleButton.setVisibility(View.GONE);
+ } else if (player == null) {
+ setButtonEnabled(false, shuffleButton);
+ } else {
+ shuffleButton.setAlpha(player.getShuffleModeEnabled() ? 1f : 0.3f);
+ shuffleButton.setEnabled(true);
+ shuffleButton.setVisibility(View.VISIBLE);
+ }
+ }
+
private void updateTimeBarMode() {
if (player == null) {
return;
@@ -1080,7 +1148,8 @@ public class PlaybackControlView extends FrameLayout {
@Override
public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
- // TODO: Update UI.
+ updateShuffleButton();
+ updateNavigation();
}
@Override
@@ -1134,6 +1203,8 @@ public class PlaybackControlView extends FrameLayout {
} else if (repeatToggleButton == view) {
controlDispatcher.dispatchSetRepeatMode(player, RepeatModeUtil.getNextRepeatMode(
player.getRepeatMode(), repeatToggleModes));
+ } else if (shuffleButton == view) {
+ controlDispatcher.dispatchSetShuffleModeEnabled(player, !player.getShuffleModeEnabled());
}
}
hideAfterTimeout();
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 0a531375c1..a8926f9ecc 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
@@ -655,6 +655,16 @@ public final class SimpleExoPlayerView extends FrameLayout {
controller.setRepeatToggleModes(repeatToggleModes);
}
+ /**
+ * Sets whether the shuffle button is shown.
+ *
+ * @param showShuffleButton Whether the shuffle button is shown.
+ */
+ public void setShowShuffleButton(boolean showShuffleButton) {
+ Assertions.checkState(controller != null);
+ controller.setShowShuffleButton(showShuffleButton);
+ }
+
/**
* Sets whether the time bar should show all windows, as opposed to just the current one.
*
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 407329890d..159844c234 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
@@ -34,6 +34,9 @@
+
+
diff --git a/library/ui/src/main/res/values/attrs.xml b/library/ui/src/main/res/values/attrs.xml
index d1f45228b1..9b701d5ba5 100644
--- a/library/ui/src/main/res/values/attrs.xml
+++ b/library/ui/src/main/res/values/attrs.xml
@@ -39,6 +39,7 @@
+
@@ -64,6 +65,7 @@
+