mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Allow customisation of various icons in PlayerControlView
Before this change: The only way to customize the icons was to override the drawables, e.g. * `exo_styled_controls_play` * `exo_styled_controls_pause` However, that would set the drawables globally and prevent users from customizing the icons **per** PlayerView. After the change, it is possible to provide drawable icons in the xml layout directly via `<androidx.media3.ui.PlayerView>` and * `app:play_icon="@drawable/...` * `app:pause_icon="@drawable/...` * `app:vr_icon="@drawable/...` * `app:fullscreen_exit_icon="@drawable/...` * `app:next_icon="@drawable/...` Note: Two buttons that are left out of this change are fast-forward and rewind. They are more complicated due to layout insertion and customization with seek back/forward increments in the TextView. Issue: androidx/media#1200 PiperOrigin-RevId: 639832741
This commit is contained in:
parent
64890a95da
commit
d35bc176ff
@ -201,6 +201,10 @@
|
||||
error state with the given error information
|
||||
([#543](https://github.com/androidx/media/issues/543)).
|
||||
* UI:
|
||||
* Add customisation of various icons in `PlayerControlView` through xml
|
||||
attributes to allow different drawables per `PlayerView` instance,
|
||||
rather than global overrides
|
||||
([#1200](https://github.com/androidx/media/issues/1200)).
|
||||
* Downloads:
|
||||
* OkHttp Extension:
|
||||
* Cronet Extension:
|
||||
|
@ -64,7 +64,6 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.res.ResourcesCompat;
|
||||
@ -165,10 +164,12 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
* PlayerControlView}, and will be propagated to the inflated {@link DefaultTimeBar}.
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Overriding drawables</h2>
|
||||
* <h2>Overriding drawables globally</h2>
|
||||
*
|
||||
* The drawables used by {@code PlayerControlView} can be overridden by drawables with the same
|
||||
* names defined in your application. The drawables that can be overridden are:
|
||||
* names defined in your application. Note that these icons will be the same across all usages of
|
||||
* {@code PlayerView}/{@code PlayerControlView} in your app. The drawables that can be overridden
|
||||
* are:
|
||||
*
|
||||
* <ul>
|
||||
* <li><b>{@code exo_styled_controls_play}</b> - The play icon.
|
||||
@ -187,6 +188,86 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
* disabled.
|
||||
* <li><b>{@code exo_styled_controls_shuffle_on}</b> - The shuffle icon when shuffling is enabled.
|
||||
* <li><b>{@code exo_styled_controls_vr}</b> - The VR icon.
|
||||
* <li><b>{@code exo_styled_controls_fullscreen_enter}</b> - The fullscreen icon for when the
|
||||
* player is minimized.
|
||||
* <li><b>{@code exo_styled_controls_fullscreen_exit}</b> - The fullscreen icon for when the
|
||||
* player is in fullscreen mode.
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Overriding drawables locally</h2>
|
||||
*
|
||||
* If you want to customize drawable per PlayerView instance, you can use the following attributes:
|
||||
* {@code PlayerView}/{@code PlayerControlView} in your app. The drawables that can be overridden
|
||||
* are:
|
||||
*
|
||||
* <ul>
|
||||
* <li><b>{@code play_icon}</b> - The drawable resource ID for the play/pause button when play is
|
||||
* shown.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_play}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code pause_icon}</b> - The drawable resource ID for the play/pause button when pause
|
||||
* is shown.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_pause}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code previous_icon}</b> - The drawable resource ID for the previous button.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_previous}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code next_icon}</b> - The drawable resource ID for the next button.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_next}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code repeat_off_icon}</b> - The drawable resource ID for the repeat button when the
|
||||
* mode is {@code none}.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_repeat_off}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code repeat_one_icon}</b> - The drawable resource ID for the repeat button when the
|
||||
* mode is {@code one}.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_repeat_one}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code repeat_all_icon}</b> - The drawable resource ID for the repeat button when the
|
||||
* mode is {@code all}.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_repeat_all}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code shuffle_on_icon}</b> - The drawable resource ID for the repeat button when the
|
||||
* mode is {@code one}.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_shuffle_on}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code shuffle_off_icon}</b> - The drawable resource ID for the repeat button when the
|
||||
* mode is {@code all}.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_shuffle_off}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code subtitle_on_icon}</b> - The drawable resource ID for the subtitle button when the
|
||||
* text track is on.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_subtitle_on}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code subtitle_off_icon}</b> - The drawable resource ID for the subtitle button when
|
||||
* the text track is off.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_subtitle_off}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code vr_icon}</b> - The drawable resource ID for the VR button.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_vr}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code fullscreen_enter_icon}</b> - The drawable resource ID for the fullscreen button
|
||||
* when the player is minimized.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_fullscreen_enter}</b>
|
||||
* </ul>
|
||||
* <li><b>{@code fullscreen_exit_icon}</b> - The drawable resource ID for the fullscreen button
|
||||
* when the player is in fullscreen mode.
|
||||
* <ul>
|
||||
* <li>Default: <b>{@code @drawable/exo_styled_controls_fullscreen_exit}</b>
|
||||
* </ul>
|
||||
* </ul>
|
||||
*/
|
||||
@UnstableApi
|
||||
@ -282,16 +363,16 @@ public class PlayerControlView extends FrameLayout {
|
||||
private final PopupWindow settingsWindow;
|
||||
private final int settingsWindowMargin;
|
||||
|
||||
@Nullable private final View previousButton;
|
||||
@Nullable private final View nextButton;
|
||||
@Nullable private final View playPauseButton;
|
||||
@Nullable private final ImageView previousButton;
|
||||
@Nullable private final ImageView nextButton;
|
||||
@Nullable private final ImageView playPauseButton;
|
||||
@Nullable private final View fastForwardButton;
|
||||
@Nullable private final View rewindButton;
|
||||
@Nullable private final TextView fastForwardButtonTextView;
|
||||
@Nullable private final TextView rewindButtonTextView;
|
||||
@Nullable private final ImageView repeatToggleButton;
|
||||
@Nullable private final ImageView shuffleButton;
|
||||
@Nullable private final View vrButton;
|
||||
@Nullable private final ImageView vrButton;
|
||||
@Nullable private final ImageView subtitleButton;
|
||||
@Nullable private final ImageView fullScreenButton;
|
||||
@Nullable private final ImageView minimalFullScreenButton;
|
||||
@ -307,6 +388,8 @@ public class PlayerControlView extends FrameLayout {
|
||||
private final Timeline.Window window;
|
||||
private final Runnable updateProgressAction;
|
||||
|
||||
private final Drawable playButtonDrawable;
|
||||
private final Drawable pauseButtonDrawable;
|
||||
private final Drawable repeatOffButtonDrawable;
|
||||
private final Drawable repeatOneButtonDrawable;
|
||||
private final Drawable repeatAllButtonDrawable;
|
||||
@ -380,6 +463,21 @@ public class PlayerControlView extends FrameLayout {
|
||||
@Nullable AttributeSet playbackAttrs) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
int controllerLayoutId = R.layout.exo_player_control_view;
|
||||
int playDrawableResId = R.drawable.exo_styled_controls_play;
|
||||
int pauseDrawableResId = R.drawable.exo_styled_controls_pause;
|
||||
int nextDrawableResId = R.drawable.exo_styled_controls_next;
|
||||
int previousDrawableResId = R.drawable.exo_styled_controls_previous;
|
||||
int fullScreenExitDrawableResId = R.drawable.exo_styled_controls_fullscreen_exit;
|
||||
int fullScreenEnterDrawableResId = R.drawable.exo_styled_controls_fullscreen_enter;
|
||||
int repeatOffDrawableResId = R.drawable.exo_styled_controls_repeat_off;
|
||||
int repeatOneDrawableResId = R.drawable.exo_styled_controls_repeat_one;
|
||||
int repeatAllDrawableResId = R.drawable.exo_styled_controls_repeat_all;
|
||||
int shuffleOnDrawableResId = R.drawable.exo_styled_controls_shuffle_on;
|
||||
int shuffleOffDrawableResId = R.drawable.exo_styled_controls_shuffle_off;
|
||||
int subtitleOnDrawableResId = R.drawable.exo_styled_controls_subtitle_on;
|
||||
int subtitleOffDrawableResId = R.drawable.exo_styled_controls_subtitle_off;
|
||||
int vrDrawableResId = R.drawable.exo_styled_controls_vr;
|
||||
|
||||
showPlayButtonIfSuppressed = true;
|
||||
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
|
||||
repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
|
||||
@ -402,6 +500,38 @@ public class PlayerControlView extends FrameLayout {
|
||||
try {
|
||||
controllerLayoutId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_controller_layout_id, controllerLayoutId);
|
||||
playDrawableResId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_play_icon, playDrawableResId);
|
||||
pauseDrawableResId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_pause_icon, pauseDrawableResId);
|
||||
nextDrawableResId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_next_icon, nextDrawableResId);
|
||||
previousDrawableResId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_previous_icon, previousDrawableResId);
|
||||
fullScreenExitDrawableResId =
|
||||
a.getResourceId(
|
||||
R.styleable.PlayerControlView_fullscreen_exit_icon, fullScreenExitDrawableResId);
|
||||
fullScreenEnterDrawableResId =
|
||||
a.getResourceId(
|
||||
R.styleable.PlayerControlView_fullscreen_enter_icon, fullScreenEnterDrawableResId);
|
||||
repeatOffDrawableResId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_repeat_off_icon, repeatOffDrawableResId);
|
||||
repeatOneDrawableResId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_repeat_one_icon, repeatOneDrawableResId);
|
||||
repeatAllDrawableResId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_repeat_all_icon, repeatAllDrawableResId);
|
||||
shuffleOnDrawableResId =
|
||||
a.getResourceId(R.styleable.PlayerControlView_shuffle_on_icon, shuffleOnDrawableResId);
|
||||
shuffleOffDrawableResId =
|
||||
a.getResourceId(
|
||||
R.styleable.PlayerControlView_shuffle_off_icon, shuffleOffDrawableResId);
|
||||
subtitleOnDrawableResId =
|
||||
a.getResourceId(
|
||||
R.styleable.PlayerControlView_subtitle_on_icon, subtitleOnDrawableResId);
|
||||
subtitleOffDrawableResId =
|
||||
a.getResourceId(
|
||||
R.styleable.PlayerControlView_subtitle_off_icon, subtitleOffDrawableResId);
|
||||
vrDrawableResId = a.getResourceId(R.styleable.PlayerControlView_vr_icon, vrDrawableResId);
|
||||
showTimeoutMs = a.getInt(R.styleable.PlayerControlView_show_timeout, showTimeoutMs);
|
||||
repeatToggleModes = getRepeatToggleModes(a, repeatToggleModes);
|
||||
showRewindButton =
|
||||
@ -501,10 +631,13 @@ public class PlayerControlView extends FrameLayout {
|
||||
}
|
||||
previousButton = findViewById(R.id.exo_prev);
|
||||
if (previousButton != null) {
|
||||
previousButton.setImageDrawable(
|
||||
getDrawable(context, context.getResources(), previousDrawableResId));
|
||||
previousButton.setOnClickListener(componentListener);
|
||||
}
|
||||
nextButton = findViewById(R.id.exo_next);
|
||||
if (nextButton != null) {
|
||||
nextButton.setImageDrawable(getDrawable(context, context.getResources(), nextDrawableResId));
|
||||
nextButton.setOnClickListener(componentListener);
|
||||
}
|
||||
Typeface typeface = ResourcesCompat.getFont(context, R.font.roboto_medium_numbers);
|
||||
@ -543,6 +676,7 @@ public class PlayerControlView extends FrameLayout {
|
||||
|
||||
vrButton = findViewById(R.id.exo_vr);
|
||||
if (vrButton != null) {
|
||||
vrButton.setImageDrawable(getDrawable(context, resources, vrDrawableResId));
|
||||
updateButton(/* enabled= */ false, vrButton);
|
||||
}
|
||||
|
||||
@ -578,10 +712,8 @@ public class PlayerControlView extends FrameLayout {
|
||||
needToHideBars = true;
|
||||
|
||||
trackNameProvider = new DefaultTrackNameProvider(getResources());
|
||||
subtitleOnButtonDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_subtitle_on);
|
||||
subtitleOffButtonDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_subtitle_off);
|
||||
subtitleOnButtonDrawable = getDrawable(context, resources, subtitleOnDrawableResId);
|
||||
subtitleOffButtonDrawable = getDrawable(context, resources, subtitleOffDrawableResId);
|
||||
subtitleOnContentDescription =
|
||||
resources.getString(R.string.exo_controls_cc_enabled_description);
|
||||
subtitleOffContentDescription =
|
||||
@ -592,20 +724,15 @@ public class PlayerControlView extends FrameLayout {
|
||||
new PlaybackSpeedAdapter(
|
||||
resources.getStringArray(R.array.exo_controls_playback_speeds), PLAYBACK_SPEEDS);
|
||||
|
||||
fullScreenExitDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_fullscreen_exit);
|
||||
fullScreenEnterDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_fullscreen_enter);
|
||||
repeatOffButtonDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_repeat_off);
|
||||
repeatOneButtonDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_repeat_one);
|
||||
repeatAllButtonDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_repeat_all);
|
||||
shuffleOnButtonDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_shuffle_on);
|
||||
shuffleOffButtonDrawable =
|
||||
getDrawable(context, resources, R.drawable.exo_styled_controls_shuffle_off);
|
||||
playButtonDrawable = getDrawable(context, resources, playDrawableResId);
|
||||
pauseButtonDrawable = getDrawable(context, resources, pauseDrawableResId);
|
||||
fullScreenExitDrawable = getDrawable(context, resources, fullScreenExitDrawableResId);
|
||||
fullScreenEnterDrawable = getDrawable(context, resources, fullScreenEnterDrawableResId);
|
||||
repeatOffButtonDrawable = getDrawable(context, resources, repeatOffDrawableResId);
|
||||
repeatOneButtonDrawable = getDrawable(context, resources, repeatOneDrawableResId);
|
||||
repeatAllButtonDrawable = getDrawable(context, resources, repeatAllDrawableResId);
|
||||
shuffleOnButtonDrawable = getDrawable(context, resources, shuffleOnDrawableResId);
|
||||
shuffleOffButtonDrawable = getDrawable(context, resources, shuffleOffDrawableResId);
|
||||
fullScreenExitContentDescription =
|
||||
resources.getString(R.string.exo_controls_fullscreen_exit_description);
|
||||
fullScreenEnterContentDescription =
|
||||
@ -1000,18 +1127,13 @@ public class PlayerControlView extends FrameLayout {
|
||||
}
|
||||
if (playPauseButton != null) {
|
||||
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed);
|
||||
@DrawableRes
|
||||
int drawableRes =
|
||||
shouldShowPlayButton
|
||||
? R.drawable.exo_styled_controls_play
|
||||
: R.drawable.exo_styled_controls_pause;
|
||||
Drawable drawable = shouldShowPlayButton ? playButtonDrawable : pauseButtonDrawable;
|
||||
@StringRes
|
||||
int stringRes =
|
||||
shouldShowPlayButton
|
||||
? R.string.exo_controls_play_description
|
||||
: R.string.exo_controls_pause_description;
|
||||
((ImageView) playPauseButton)
|
||||
.setImageDrawable(getDrawable(getContext(), resources, drawableRes));
|
||||
((ImageView) playPauseButton).setImageDrawable(drawable);
|
||||
playPauseButton.setContentDescription(resources.getString(stringRes));
|
||||
|
||||
boolean enablePlayPause = shouldEnablePlayPauseButton();
|
||||
|
@ -62,14 +62,28 @@
|
||||
<attr name="player_layout_id" format="reference"/>
|
||||
|
||||
<!-- LegacyPlayerControlView and PlayerControlView attributes -->
|
||||
<attr name="play_icon" format="reference"/>
|
||||
<attr name="pause_icon" format="reference"/>
|
||||
<attr name="repeat_off_icon" format="reference"/>
|
||||
<attr name="repeat_one_icon" format="reference"/>
|
||||
<attr name="repeat_all_icon" format="reference"/>
|
||||
<attr name="fullscreen_exit_icon" format="reference"/>
|
||||
<attr name="fullscreen_enter_icon" format="reference"/>
|
||||
<attr name="show_timeout" format="integer"/>
|
||||
<attr name="show_rewind_button" format="boolean"/>
|
||||
<attr name="show_fastforward_button" format="boolean"/>
|
||||
<attr name="show_previous_button" format="boolean"/>
|
||||
<attr name="previous_icon" format="reference"/>
|
||||
<attr name="show_next_button" format="boolean"/>
|
||||
<attr name="next_icon" format="reference"/>
|
||||
<attr name="show_shuffle_button" format="boolean"/>
|
||||
<attr name="shuffle_on_icon" format="reference"/>
|
||||
<attr name="shuffle_off_icon" format="reference"/>
|
||||
<attr name="show_subtitle_button" format="boolean"/>
|
||||
<attr name="subtitle_on_icon" format="reference"/>
|
||||
<attr name="subtitle_off_icon" format="reference"/>
|
||||
<attr name="show_vr_button" format="boolean"/>
|
||||
<attr name="vr_icon" format="reference"/>
|
||||
<attr name="time_bar_min_update_interval" format="integer"/>
|
||||
<attr name="controller_layout_id" format="reference"/>
|
||||
<attr name="animation_enabled" format="boolean"/>
|
||||
@ -114,12 +128,26 @@
|
||||
<!-- PlayerControlView attributes -->
|
||||
<attr name="show_timeout"/>
|
||||
<attr name="repeat_toggle_modes"/>
|
||||
<attr name="repeat_off_icon"/>
|
||||
<attr name="repeat_one_icon"/>
|
||||
<attr name="repeat_all_icon"/>
|
||||
<attr name="show_shuffle_button"/>
|
||||
<attr name="shuffle_off_icon"/>
|
||||
<attr name="shuffle_on_icon"/>
|
||||
<attr name="show_subtitle_button"/>
|
||||
<attr name="subtitle_off_icon"/>
|
||||
<attr name="subtitle_on_icon"/>
|
||||
<attr name="show_vr_button"/>
|
||||
<attr name="vr_icon"/>
|
||||
<attr name="time_bar_min_update_interval"/>
|
||||
<attr name="controller_layout_id"/>
|
||||
<attr name="animation_enabled"/>
|
||||
<attr name="play_icon"/>
|
||||
<attr name="pause_icon"/>
|
||||
<attr name="fullscreen_enter_icon"/>
|
||||
<attr name="fullscreen_exit_icon"/>
|
||||
<attr name="next_icon"/>
|
||||
<attr name="previous_icon"/>
|
||||
<!-- DefaultTimeBar attributes -->
|
||||
<attr name="bar_height"/>
|
||||
<attr name="bar_gravity"/>
|
||||
@ -171,16 +199,30 @@
|
||||
<declare-styleable name="PlayerControlView">
|
||||
<attr name="show_timeout"/>
|
||||
<attr name="repeat_toggle_modes"/>
|
||||
<attr name="repeat_off_icon"/>
|
||||
<attr name="repeat_one_icon"/>
|
||||
<attr name="repeat_all_icon"/>
|
||||
<attr name="show_rewind_button"/>
|
||||
<attr name="show_fastforward_button"/>
|
||||
<attr name="show_previous_button"/>
|
||||
<attr name="previous_icon"/>
|
||||
<attr name="show_next_button"/>
|
||||
<attr name="next_icon"/>
|
||||
<attr name="show_shuffle_button"/>
|
||||
<attr name="shuffle_on_icon"/>
|
||||
<attr name="shuffle_off_icon"/>
|
||||
<attr name="show_subtitle_button"/>
|
||||
<attr name="subtitle_on_icon"/>
|
||||
<attr name="subtitle_off_icon"/>
|
||||
<attr name="show_vr_button"/>
|
||||
<attr name="vr_icon"/>
|
||||
<attr name="time_bar_min_update_interval"/>
|
||||
<attr name="controller_layout_id"/>
|
||||
<attr name="animation_enabled"/>
|
||||
<attr name="play_icon"/>
|
||||
<attr name="pause_icon"/>
|
||||
<attr name="fullscreen_exit_icon"/>
|
||||
<attr name="fullscreen_enter_icon"/>
|
||||
<!-- DefaultTimeBar attributes -->
|
||||
<attr name="bar_height"/>
|
||||
<attr name="bar_gravity"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user