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:
jbibik 2024-06-03 10:29:16 -07:00 committed by Copybara-Service
parent 64890a95da
commit d35bc176ff
3 changed files with 200 additions and 32 deletions

View File

@ -201,6 +201,10 @@
error state with the given error information error state with the given error information
([#543](https://github.com/androidx/media/issues/543)). ([#543](https://github.com/androidx/media/issues/543)).
* UI: * 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: * Downloads:
* OkHttp Extension: * OkHttp Extension:
* Cronet Extension: * Cronet Extension:

View File

@ -64,7 +64,6 @@ import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.content.res.ResourcesCompat; 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}. * PlayerControlView}, and will be propagated to the inflated {@link DefaultTimeBar}.
* </ul> * </ul>
* *
* <h2>Overriding drawables</h2> * <h2>Overriding drawables globally</h2>
* *
* The drawables used by {@code PlayerControlView} can be overridden by drawables with the same * 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> * <ul>
* <li><b>{@code exo_styled_controls_play}</b> - The play icon. * <li><b>{@code exo_styled_controls_play}</b> - The play icon.
@ -187,6 +188,86 @@ import java.util.concurrent.CopyOnWriteArrayList;
* disabled. * disabled.
* <li><b>{@code exo_styled_controls_shuffle_on}</b> - The shuffle icon when shuffling is enabled. * <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_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> * </ul>
*/ */
@UnstableApi @UnstableApi
@ -282,16 +363,16 @@ public class PlayerControlView extends FrameLayout {
private final PopupWindow settingsWindow; private final PopupWindow settingsWindow;
private final int settingsWindowMargin; private final int settingsWindowMargin;
@Nullable private final View previousButton; @Nullable private final ImageView previousButton;
@Nullable private final View nextButton; @Nullable private final ImageView nextButton;
@Nullable private final View playPauseButton; @Nullable private final ImageView playPauseButton;
@Nullable private final View fastForwardButton; @Nullable private final View fastForwardButton;
@Nullable private final View rewindButton; @Nullable private final View rewindButton;
@Nullable private final TextView fastForwardButtonTextView; @Nullable private final TextView fastForwardButtonTextView;
@Nullable private final TextView rewindButtonTextView; @Nullable private final TextView rewindButtonTextView;
@Nullable private final ImageView repeatToggleButton; @Nullable private final ImageView repeatToggleButton;
@Nullable private final ImageView shuffleButton; @Nullable private final ImageView shuffleButton;
@Nullable private final View vrButton; @Nullable private final ImageView vrButton;
@Nullable private final ImageView subtitleButton; @Nullable private final ImageView subtitleButton;
@Nullable private final ImageView fullScreenButton; @Nullable private final ImageView fullScreenButton;
@Nullable private final ImageView minimalFullScreenButton; @Nullable private final ImageView minimalFullScreenButton;
@ -307,6 +388,8 @@ public class PlayerControlView extends FrameLayout {
private final Timeline.Window window; private final Timeline.Window window;
private final Runnable updateProgressAction; private final Runnable updateProgressAction;
private final Drawable playButtonDrawable;
private final Drawable pauseButtonDrawable;
private final Drawable repeatOffButtonDrawable; private final Drawable repeatOffButtonDrawable;
private final Drawable repeatOneButtonDrawable; private final Drawable repeatOneButtonDrawable;
private final Drawable repeatAllButtonDrawable; private final Drawable repeatAllButtonDrawable;
@ -380,6 +463,21 @@ public class PlayerControlView extends FrameLayout {
@Nullable AttributeSet playbackAttrs) { @Nullable AttributeSet playbackAttrs) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
int controllerLayoutId = R.layout.exo_player_control_view; 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; showPlayButtonIfSuppressed = true;
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS; showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES; repeatToggleModes = DEFAULT_REPEAT_TOGGLE_MODES;
@ -402,6 +500,38 @@ public class PlayerControlView extends FrameLayout {
try { try {
controllerLayoutId = controllerLayoutId =
a.getResourceId(R.styleable.PlayerControlView_controller_layout_id, 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); showTimeoutMs = a.getInt(R.styleable.PlayerControlView_show_timeout, showTimeoutMs);
repeatToggleModes = getRepeatToggleModes(a, repeatToggleModes); repeatToggleModes = getRepeatToggleModes(a, repeatToggleModes);
showRewindButton = showRewindButton =
@ -501,10 +631,13 @@ public class PlayerControlView extends FrameLayout {
} }
previousButton = findViewById(R.id.exo_prev); previousButton = findViewById(R.id.exo_prev);
if (previousButton != null) { if (previousButton != null) {
previousButton.setImageDrawable(
getDrawable(context, context.getResources(), previousDrawableResId));
previousButton.setOnClickListener(componentListener); previousButton.setOnClickListener(componentListener);
} }
nextButton = findViewById(R.id.exo_next); nextButton = findViewById(R.id.exo_next);
if (nextButton != null) { if (nextButton != null) {
nextButton.setImageDrawable(getDrawable(context, context.getResources(), nextDrawableResId));
nextButton.setOnClickListener(componentListener); nextButton.setOnClickListener(componentListener);
} }
Typeface typeface = ResourcesCompat.getFont(context, R.font.roboto_medium_numbers); 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); vrButton = findViewById(R.id.exo_vr);
if (vrButton != null) { if (vrButton != null) {
vrButton.setImageDrawable(getDrawable(context, resources, vrDrawableResId));
updateButton(/* enabled= */ false, vrButton); updateButton(/* enabled= */ false, vrButton);
} }
@ -578,10 +712,8 @@ public class PlayerControlView extends FrameLayout {
needToHideBars = true; needToHideBars = true;
trackNameProvider = new DefaultTrackNameProvider(getResources()); trackNameProvider = new DefaultTrackNameProvider(getResources());
subtitleOnButtonDrawable = subtitleOnButtonDrawable = getDrawable(context, resources, subtitleOnDrawableResId);
getDrawable(context, resources, R.drawable.exo_styled_controls_subtitle_on); subtitleOffButtonDrawable = getDrawable(context, resources, subtitleOffDrawableResId);
subtitleOffButtonDrawable =
getDrawable(context, resources, R.drawable.exo_styled_controls_subtitle_off);
subtitleOnContentDescription = subtitleOnContentDescription =
resources.getString(R.string.exo_controls_cc_enabled_description); resources.getString(R.string.exo_controls_cc_enabled_description);
subtitleOffContentDescription = subtitleOffContentDescription =
@ -592,20 +724,15 @@ public class PlayerControlView extends FrameLayout {
new PlaybackSpeedAdapter( new PlaybackSpeedAdapter(
resources.getStringArray(R.array.exo_controls_playback_speeds), PLAYBACK_SPEEDS); resources.getStringArray(R.array.exo_controls_playback_speeds), PLAYBACK_SPEEDS);
fullScreenExitDrawable = playButtonDrawable = getDrawable(context, resources, playDrawableResId);
getDrawable(context, resources, R.drawable.exo_styled_controls_fullscreen_exit); pauseButtonDrawable = getDrawable(context, resources, pauseDrawableResId);
fullScreenEnterDrawable = fullScreenExitDrawable = getDrawable(context, resources, fullScreenExitDrawableResId);
getDrawable(context, resources, R.drawable.exo_styled_controls_fullscreen_enter); fullScreenEnterDrawable = getDrawable(context, resources, fullScreenEnterDrawableResId);
repeatOffButtonDrawable = repeatOffButtonDrawable = getDrawable(context, resources, repeatOffDrawableResId);
getDrawable(context, resources, R.drawable.exo_styled_controls_repeat_off); repeatOneButtonDrawable = getDrawable(context, resources, repeatOneDrawableResId);
repeatOneButtonDrawable = repeatAllButtonDrawable = getDrawable(context, resources, repeatAllDrawableResId);
getDrawable(context, resources, R.drawable.exo_styled_controls_repeat_one); shuffleOnButtonDrawable = getDrawable(context, resources, shuffleOnDrawableResId);
repeatAllButtonDrawable = shuffleOffButtonDrawable = getDrawable(context, resources, shuffleOffDrawableResId);
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);
fullScreenExitContentDescription = fullScreenExitContentDescription =
resources.getString(R.string.exo_controls_fullscreen_exit_description); resources.getString(R.string.exo_controls_fullscreen_exit_description);
fullScreenEnterContentDescription = fullScreenEnterContentDescription =
@ -1000,18 +1127,13 @@ public class PlayerControlView extends FrameLayout {
} }
if (playPauseButton != null) { if (playPauseButton != null) {
boolean shouldShowPlayButton = Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed); boolean shouldShowPlayButton = Util.shouldShowPlayButton(player, showPlayButtonIfSuppressed);
@DrawableRes Drawable drawable = shouldShowPlayButton ? playButtonDrawable : pauseButtonDrawable;
int drawableRes =
shouldShowPlayButton
? R.drawable.exo_styled_controls_play
: R.drawable.exo_styled_controls_pause;
@StringRes @StringRes
int stringRes = int stringRes =
shouldShowPlayButton shouldShowPlayButton
? R.string.exo_controls_play_description ? R.string.exo_controls_play_description
: R.string.exo_controls_pause_description; : R.string.exo_controls_pause_description;
((ImageView) playPauseButton) ((ImageView) playPauseButton).setImageDrawable(drawable);
.setImageDrawable(getDrawable(getContext(), resources, drawableRes));
playPauseButton.setContentDescription(resources.getString(stringRes)); playPauseButton.setContentDescription(resources.getString(stringRes));
boolean enablePlayPause = shouldEnablePlayPauseButton(); boolean enablePlayPause = shouldEnablePlayPauseButton();

View File

@ -62,14 +62,28 @@
<attr name="player_layout_id" format="reference"/> <attr name="player_layout_id" format="reference"/>
<!-- LegacyPlayerControlView and PlayerControlView attributes --> <!-- 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_timeout" format="integer"/>
<attr name="show_rewind_button" format="boolean"/> <attr name="show_rewind_button" format="boolean"/>
<attr name="show_fastforward_button" format="boolean"/> <attr name="show_fastforward_button" format="boolean"/>
<attr name="show_previous_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="show_next_button" format="boolean"/>
<attr name="next_icon" format="reference"/>
<attr name="show_shuffle_button" format="boolean"/> <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="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="show_vr_button" format="boolean"/>
<attr name="vr_icon" format="reference"/>
<attr name="time_bar_min_update_interval" format="integer"/> <attr name="time_bar_min_update_interval" format="integer"/>
<attr name="controller_layout_id" format="reference"/> <attr name="controller_layout_id" format="reference"/>
<attr name="animation_enabled" format="boolean"/> <attr name="animation_enabled" format="boolean"/>
@ -114,12 +128,26 @@
<!-- PlayerControlView attributes --> <!-- PlayerControlView attributes -->
<attr name="show_timeout"/> <attr name="show_timeout"/>
<attr name="repeat_toggle_modes"/> <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="show_shuffle_button"/>
<attr name="shuffle_off_icon"/>
<attr name="shuffle_on_icon"/>
<attr name="show_subtitle_button"/> <attr name="show_subtitle_button"/>
<attr name="subtitle_off_icon"/>
<attr name="subtitle_on_icon"/>
<attr name="show_vr_button"/> <attr name="show_vr_button"/>
<attr name="vr_icon"/>
<attr name="time_bar_min_update_interval"/> <attr name="time_bar_min_update_interval"/>
<attr name="controller_layout_id"/> <attr name="controller_layout_id"/>
<attr name="animation_enabled"/> <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 --> <!-- DefaultTimeBar attributes -->
<attr name="bar_height"/> <attr name="bar_height"/>
<attr name="bar_gravity"/> <attr name="bar_gravity"/>
@ -171,16 +199,30 @@
<declare-styleable name="PlayerControlView"> <declare-styleable name="PlayerControlView">
<attr name="show_timeout"/> <attr name="show_timeout"/>
<attr name="repeat_toggle_modes"/> <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_rewind_button"/>
<attr name="show_fastforward_button"/> <attr name="show_fastforward_button"/>
<attr name="show_previous_button"/> <attr name="show_previous_button"/>
<attr name="previous_icon"/>
<attr name="show_next_button"/> <attr name="show_next_button"/>
<attr name="next_icon"/>
<attr name="show_shuffle_button"/> <attr name="show_shuffle_button"/>
<attr name="shuffle_on_icon"/>
<attr name="shuffle_off_icon"/>
<attr name="show_subtitle_button"/> <attr name="show_subtitle_button"/>
<attr name="subtitle_on_icon"/>
<attr name="subtitle_off_icon"/>
<attr name="show_vr_button"/> <attr name="show_vr_button"/>
<attr name="vr_icon"/>
<attr name="time_bar_min_update_interval"/> <attr name="time_bar_min_update_interval"/>
<attr name="controller_layout_id"/> <attr name="controller_layout_id"/>
<attr name="animation_enabled"/> <attr name="animation_enabled"/>
<attr name="play_icon"/>
<attr name="pause_icon"/>
<attr name="fullscreen_exit_icon"/>
<attr name="fullscreen_enter_icon"/>
<!-- DefaultTimeBar attributes --> <!-- DefaultTimeBar attributes -->
<attr name="bar_height"/> <attr name="bar_height"/>
<attr name="bar_gravity"/> <attr name="bar_gravity"/>