Add artwork support to SimpleExoPlayerView + misc improvements

This commit is contained in:
Oliver Woodman 2016-10-27 12:47:26 +01:00
parent 0c8f3c7270
commit c4b4e84579
8 changed files with 271 additions and 111 deletions

View File

@ -71,36 +71,30 @@ import com.google.android.exoplayer2.util.Util;
// Standard genres.
private static final String[] STANDARD_GENRES = new String[] {
// These are the official ID3v1 genres.
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
"Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap",
"Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
"Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient",
"Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical",
"Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise",
"AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative",
"Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave",
"Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
"Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap",
"Pop/Funk", "Jungle", "Native American", "Cabaret", "New Wave",
"Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi", "Tribal",
"Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll",
"Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip-Hop", "Jazz",
"Metal", "New Age", "Oldies", "Other", "Pop", "R&B", "Rap", "Reggae", "Rock", "Techno",
"Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro-Techno",
"Ambient", "Trip-Hop", "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
"Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul",
"Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic",
"Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk", "Eurodance", "Dream",
"Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
"Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer",
"Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll",
"Hard Rock",
// These were made up by the authors of Winamp but backported into the ID3 spec.
"Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion",
"Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
"Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock",
"Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
"Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony",
"Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club",
"Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul",
"Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House",
"Dance Hall",
// These were also invented by the Winamp folks but ignored by the ID3 authors.
"Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
"BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap",
"Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
"Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "Jpop",
"Synthpop"
// These were made up by the authors of Winamp and later added to the ID3 spec.
"Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin", "Revival",
"Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock",
"Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour",
"Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
"Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad",
"Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A capella",
"Euro-House", "Dance Hall",
// These were med up by the authors of Winamp but have not been added to the ID3 spec.
"Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", "BritPop", "Negerpunk",
"Polsk Punk", "Beat", "Christian Gangsta Rap", "Heavy Metal", "Black Metal", "Crossover",
"Contemporary Christian", "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime",
"Jpop", "Synthpop"
};
private static final String LANGUAGE_UNDEFINED = "und";

View File

@ -17,16 +17,26 @@ package com.google.android.exoplayer2.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.IntDef;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import com.google.android.exoplayer2.R;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* A {@link FrameLayout} that resizes itself to match a specified aspect ratio.
*/
public final class AspectRatioFrameLayout extends FrameLayout {
/**
* Resize modes for {@link AspectRatioFrameLayout}.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({RESIZE_MODE_FIT, RESIZE_MODE_FIXED_WIDTH, RESIZE_MODE_FIXED_HEIGHT})
public @interface ResizeMode {}
/**
* Either the width or height is decreased to obtain the desired aspect ratio.
*/
@ -85,12 +95,11 @@ public final class AspectRatioFrameLayout extends FrameLayout {
}
/**
* Sets the resize mode which can be of value {@link #RESIZE_MODE_FIT},
* {@link #RESIZE_MODE_FIXED_HEIGHT} or {@link #RESIZE_MODE_FIXED_WIDTH}.
* Sets the resize mode.
*
* @param resizeMode The resize mode.
*/
public void setResizeMode(int resizeMode) {
public void setResizeMode(@ResizeMode int resizeMode) {
if (this.resizeMode != resizeMode) {
this.resizeMode = resizeMode;
requestLayout();

View File

@ -120,7 +120,7 @@ public class PlaybackControlView extends FrameLayout {
public PlaybackControlView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
int layoutResourceId = R.layout.exo_playback_control_view;
int controllerLayoutId = R.layout.exo_playback_control_view;
rewindMs = DEFAULT_REWIND_MS;
fastForwardMs = DEFAULT_FAST_FORWARD_MS;
showTimeoutMs = DEFAULT_SHOW_TIMEOUT_MS;
@ -132,8 +132,8 @@ public class PlaybackControlView extends FrameLayout {
fastForwardMs = a.getInt(R.styleable.PlaybackControlView_fastforward_increment,
fastForwardMs);
showTimeoutMs = a.getInt(R.styleable.PlaybackControlView_show_timeout, showTimeoutMs);
layoutResourceId = a.getResourceId(R.styleable.PlaybackControlView_controller_layout_id,
layoutResourceId);
controllerLayoutId = a.getResourceId(R.styleable.PlaybackControlView_controller_layout_id,
controllerLayoutId);
} finally {
a.recycle();
}
@ -143,7 +143,7 @@ public class PlaybackControlView extends FrameLayout {
formatter = new Formatter(formatBuilder, Locale.getDefault());
componentListener = new ComponentListener();
LayoutInflater.from(context).inflate(layoutResourceId, this);
LayoutInflater.from(context).inflate(controllerLayoutId, this);
time = (TextView) findViewById(R.id.exo_time);
timeCurrent = (TextView) findViewById(R.id.exo_time_current);
progressBar = (SeekBar) findViewById(R.id.exo_progress);

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.ui;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@ -27,16 +28,22 @@ import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.R;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextRenderer;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout.ResizeMode;
import com.google.android.exoplayer2.util.Assertions;
import java.util.List;
/**
@ -45,15 +52,22 @@ import java.util.List;
@TargetApi(16)
public final class SimpleExoPlayerView extends FrameLayout {
private final View surfaceView;
private static final int SURFACE_TYPE_NONE = 0;
private static final int SURFACE_TYPE_SURFACE_VIEW = 1;
private static final int SURFACE_TYPE_TEXTURE_VIEW = 2;
private final ViewGroup videoFrame;
private final AspectRatioFrameLayout aspectRatioVideoFrame;
private final View shutterView;
private final SubtitleView subtitleLayout;
private final AspectRatioFrameLayout layout;
private final View surfaceView;
private final ImageView artworkView;
private final SubtitleView subtitleView;
private final PlaybackControlView controller;
private final ComponentListener componentListener;
private SimpleExoPlayer player;
private boolean useController = true;
private boolean useController;
private boolean useArtwork;
private int controllerShowTimeoutMs;
public SimpleExoPlayerView(Context context) {
@ -67,7 +81,10 @@ public final class SimpleExoPlayerView extends FrameLayout {
public SimpleExoPlayerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
boolean useTextureView = false;
int playerLayoutId = R.layout.exo_simple_player_view;
boolean useArtwork = true;
boolean useController = true;
int surfaceType = SURFACE_TYPE_SURFACE_VIEW;
int resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT;
int rewindMs = PlaybackControlView.DEFAULT_REWIND_MS;
int fastForwardMs = PlaybackControlView.DEFAULT_FAST_FORWARD_MS;
@ -76,11 +93,12 @@ public final class SimpleExoPlayerView extends FrameLayout {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.SimpleExoPlayerView, 0, 0);
try {
playerLayoutId = a.getResourceId(R.styleable.SimpleExoPlayerView_player_layout_id,
playerLayoutId);
useArtwork = a.getBoolean(R.styleable.SimpleExoPlayerView_use_artwork, useArtwork);
useController = a.getBoolean(R.styleable.SimpleExoPlayerView_use_controller, useController);
useTextureView = a.getBoolean(R.styleable.SimpleExoPlayerView_use_texture_view,
useTextureView);
resizeMode = a.getInt(R.styleable.SimpleExoPlayerView_resize_mode,
AspectRatioFrameLayout.RESIZE_MODE_FIT);
surfaceType = a.getInt(R.styleable.SimpleExoPlayerView_surface_type, surfaceType);
resizeMode = a.getInt(R.styleable.SimpleExoPlayerView_resize_mode, resizeMode);
rewindMs = a.getInt(R.styleable.SimpleExoPlayerView_rewind_increment, rewindMs);
fastForwardMs = a.getInt(R.styleable.SimpleExoPlayerView_fastforward_increment,
fastForwardMs);
@ -91,35 +109,64 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
}
LayoutInflater.from(context).inflate(R.layout.exo_simple_player_view, this);
LayoutInflater.from(context).inflate(playerLayoutId, this);
componentListener = new ComponentListener();
layout = (AspectRatioFrameLayout) findViewById(R.id.exo_video_frame);
layout.setResizeMode(resizeMode);
shutterView = findViewById(R.id.exo_shutter);
subtitleLayout = (SubtitleView) findViewById(R.id.exo_subtitles);
subtitleLayout.setUserDefaultStyle();
subtitleLayout.setUserDefaultTextSize();
View controllerPlaceholder = findViewById(R.id.exo_controller_placeholder);
videoFrame = (ViewGroup) findViewById(R.id.exo_video_frame);
if (videoFrame != null) {
if (videoFrame instanceof AspectRatioFrameLayout) {
aspectRatioVideoFrame = (AspectRatioFrameLayout) videoFrame;
setResizeModeRaw(aspectRatioVideoFrame, resizeMode);
} else {
aspectRatioVideoFrame = null;
}
shutterView = Assertions.checkNotNull(videoFrame.findViewById(R.id.exo_shutter));
if (surfaceType != SURFACE_TYPE_NONE) {
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
surfaceView = surfaceType == SURFACE_TYPE_TEXTURE_VIEW ? new TextureView(context)
: new SurfaceView(context);
surfaceView.setLayoutParams(params);
videoFrame.addView(surfaceView, 0);
} else {
surfaceView = null;
}
} else {
aspectRatioVideoFrame = null;
shutterView = null;
surfaceView = null;
}
controller = new PlaybackControlView(context, attrs);
artworkView = (ImageView) findViewById(R.id.exo_artwork);
this.useArtwork = useArtwork && artworkView != null;
subtitleView = (SubtitleView) findViewById(R.id.exo_subtitles);
if (subtitleView != null) {
subtitleView.setUserDefaultStyle();
subtitleView.setUserDefaultTextSize();
}
PlaybackControlView controller = (PlaybackControlView) findViewById(R.id.exo_controller);
if (controller != null) {
controller.setRewindIncrementMs(rewindMs);
controller.setFastForwardIncrementMs(fastForwardMs);
} else {
View controllerPlaceholder = findViewById(R.id.exo_controller_placeholder);
if (controllerPlaceholder != null) {
// Note: rewindMs and fastForwardMs are passed via attrs, so we don't need to make explicit
// calls to set them.
controller = new PlaybackControlView(context, attrs);
controller.setLayoutParams(controllerPlaceholder.getLayoutParams());
controller.hide();
this.controllerShowTimeoutMs = controllerShowTimeoutMs;
ViewGroup parent = ((ViewGroup) controllerPlaceholder.getParent());
int controllerIndex = parent.indexOfChild(controllerPlaceholder);
parent.removeView(controllerPlaceholder);
parent.addView(controller, controllerIndex);
View view = useTextureView ? new TextureView(context) : new SurfaceView(context);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
view.setLayoutParams(params);
surfaceView = view;
layout.addView(surfaceView, 0);
}
}
this.controller = controller;
this.controllerShowTimeoutMs = controller != null ? controllerShowTimeoutMs : 0;
this.useController = useController && controller != null;
hideController();
}
/**
@ -150,6 +197,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
if (useController) {
controller.setPlayer(player);
}
if (shutterView != null) {
shutterView.setVisibility(VISIBLE);
}
if (player != null) {
if (surfaceView instanceof TextureView) {
player.setVideoTextureView((TextureView) surfaceView);
@ -160,21 +210,41 @@ public final class SimpleExoPlayerView extends FrameLayout {
player.addListener(componentListener);
player.setTextOutput(componentListener);
maybeShowController(false);
updateForCurrentTrackSelections();
} else {
shutterView.setVisibility(VISIBLE);
controller.hide();
hideController();
hideArtwork();
}
}
/**
* Sets the resize mode which can be of value {@link AspectRatioFrameLayout#RESIZE_MODE_FIT},
* {@link AspectRatioFrameLayout#RESIZE_MODE_FIXED_HEIGHT} or
* {@link AspectRatioFrameLayout#RESIZE_MODE_FIXED_WIDTH}.
* Sets the resize mode.
*
* @param resizeMode The resize mode.
*/
public void setResizeMode(int resizeMode) {
layout.setResizeMode(resizeMode);
public void setResizeMode(@ResizeMode int resizeMode) {
Assertions.checkState(aspectRatioVideoFrame != null);
aspectRatioVideoFrame.setResizeMode(resizeMode);
}
/**
* Returns whether artwork is displayed if present in the media.
*/
public boolean getUseArtwork() {
return useArtwork;
}
/**
* Sets whether artwork is displayed if present in the media.
*
* @param useArtwork Whether artwork is displayed.
*/
public void setUseArtwork(boolean useArtwork) {
Assertions.checkState(!useArtwork || artworkView != null);
if (this.useArtwork != useArtwork) {
this.useArtwork = useArtwork;
updateForCurrentTrackSelections();
}
}
/**
@ -191,13 +261,14 @@ public final class SimpleExoPlayerView extends FrameLayout {
* @param useController Whether playback controls should be enabled.
*/
public void setUseController(boolean useController) {
Assertions.checkState(!useController || controller != null);
if (this.useController == useController) {
return;
}
this.useController = useController;
if (useController) {
controller.setPlayer(player);
} else {
} else if (controller != null) {
controller.hide();
controller.setPlayer(null);
}
@ -223,6 +294,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
* the controller to remain visible indefinitely.
*/
public void setControllerShowTimeoutMs(int controllerShowTimeoutMs) {
Assertions.checkState(controller != null);
this.controllerShowTimeoutMs = controllerShowTimeoutMs;
}
@ -232,6 +304,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
* @param listener The listener to be notified about visibility changes.
*/
public void setControllerVisibilityListener(PlaybackControlView.VisibilityListener listener) {
Assertions.checkState(controller != null);
controller.setVisibilityListener(listener);
}
@ -241,6 +314,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
* @param rewindMs The rewind increment in milliseconds.
*/
public void setRewindIncrementMs(int rewindMs) {
Assertions.checkState(controller != null);
controller.setRewindIncrementMs(rewindMs);
}
@ -250,6 +324,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
* @param fastForwardMs The fast forward increment in milliseconds.
*/
public void setFastForwardIncrementMs(int fastForwardMs) {
Assertions.checkState(controller != null);
controller.setFastForwardIncrementMs(fastForwardMs);
}
@ -304,6 +379,67 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
}
private void updateForCurrentTrackSelections() {
if (player == null) {
return;
}
TrackSelectionArray selections = player.getCurrentTrackSelections();
for (int i = 0; i < selections.length; i++) {
if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) {
// Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in
// onRenderedFirstFrame().
hideArtwork();
return;
}
}
// Video disabled so the shutter must be closed.
if (shutterView != null) {
shutterView.setVisibility(VISIBLE);
}
// Display artwork if enabled and available, else hide it.
if (useArtwork) {
for (int i = 0; i < selections.length; i++) {
TrackSelection selection = selections.get(i);
if (selection != null) {
for (int j = 0; j < selection.length(); j++) {
Metadata metadata = selection.getFormat(j).metadata;
if (metadata != null) {
for (int k = 0; k < metadata.length(); k++) {
Metadata.Entry metadataEntry = metadata.get(k);
if (metadataEntry instanceof ApicFrame) {
byte[] data = ((ApicFrame) metadataEntry).pictureData;;
artworkView.setImageBitmap(BitmapFactory.decodeByteArray(data, 0, data.length));
artworkView.setVisibility(VISIBLE);
return;
}
}
}
}
}
}
}
// Artwork disabled or unavailable.
hideArtwork();
}
private void hideArtwork() {
if (artworkView != null) {
artworkView.setImageResource(android.R.color.transparent); // Clears any bitmap reference.
artworkView.setVisibility(INVISIBLE);
}
}
private void hideController() {
if (controller != null) {
controller.hide();
}
}
@SuppressWarnings("ResourceType")
private static void setResizeModeRaw(AspectRatioFrameLayout aspectRatioFrame, int resizeMode) {
aspectRatioFrame.setResizeMode(resizeMode);
}
private final class ComponentListener implements SimpleExoPlayer.VideoListener,
TextRenderer.Output, ExoPlayer.EventListener {
@ -311,7 +447,9 @@ public final class SimpleExoPlayerView extends FrameLayout {
@Override
public void onCues(List<Cue> cues) {
subtitleLayout.onCues(cues);
if (subtitleView != null) {
subtitleView.onCues(cues);
}
}
// SimpleExoPlayer.VideoListener implementation
@ -319,23 +457,22 @@ public final class SimpleExoPlayerView extends FrameLayout {
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
float pixelWidthHeightRatio) {
layout.setAspectRatio(height == 0 ? 1 : (width * pixelWidthHeightRatio) / height);
if (aspectRatioVideoFrame != null) {
float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height;
aspectRatioVideoFrame.setAspectRatio(aspectRatio);
}
}
@Override
public void onRenderedFirstFrame() {
shutterView.setVisibility(GONE);
if (shutterView != null) {
shutterView.setVisibility(INVISIBLE);
}
}
@Override
public void onTracksChanged(TrackGroupArray tracks, TrackSelectionArray selections) {
for (int i = 0; i < selections.length; i++) {
if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) {
return;
}
}
// No enabled video renderers. Close the shutter.
shutterView.setVisibility(VISIBLE);
updateForCurrentTrackSelections();
}
// ExoPlayer.EventListener implementation

View File

@ -28,22 +28,22 @@
android:paddingTop="4dp"
android:orientation="horizontal">
<ImageButton android:id="@+id/exo_prev"
<ImageButton android:id="@id/exo_prev"
style="@style/ExoMediaButton.Previous"/>
<ImageButton android:id="@+id/exo_rew"
<ImageButton android:id="@id/exo_rew"
style="@style/ExoMediaButton.Rewind"/>
<ImageButton android:id="@+id/exo_play"
<ImageButton android:id="@id/exo_play"
style="@style/ExoMediaButton.Play"/>
<ImageButton android:id="@+id/exo_pause"
<ImageButton android:id="@id/exo_pause"
style="@style/ExoMediaButton.Pause"/>
<ImageButton android:id="@+id/exo_ffwd"
<ImageButton android:id="@id/exo_ffwd"
style="@style/ExoMediaButton.FastForward"/>
<ImageButton android:id="@+id/exo_next"
<ImageButton android:id="@id/exo_next"
style="@style/ExoMediaButton.Next"/>
</LinearLayout>
@ -53,7 +53,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView android:id="@+id/exo_time_current"
<TextView android:id="@id/exo_time_current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
@ -64,13 +64,13 @@
android:paddingEnd="4dp"
android:textColor="#FFBEBEBE"/>
<SeekBar android:id="@+id/exo_progress"
<SeekBar android:id="@id/exo_progress"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="32dp"
style="?android:attr/progressBarStyleHorizontal"/>
<TextView android:id="@+id/exo_time"
<TextView android:id="@id/exo_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"

View File

@ -17,23 +17,28 @@
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout android:id="@+id/exo_video_frame"
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout android:id="@id/exo_video_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<View android:id="@+id/exo_shutter"
<View android:id="@id/exo_shutter"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"/>
<com.google.android.exoplayer2.ui.SubtitleView android:id="@+id/exo_subtitles"
<com.google.android.exoplayer2.ui.SubtitleView android:id="@id/exo_subtitles"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.google.android.exoplayer2.ui.AspectRatioFrameLayout>
<View android:id="@+id/exo_controller_placeholder"
<ImageView android:id="@id/exo_artwork"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"/>
<View android:id="@id/exo_controller_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

View File

@ -14,24 +14,33 @@
limitations under the License.
-->
<resources>
<!-- Must be kept in sync with AspectRatioFrameLayout -->
<attr name="resize_mode" format="enum">
<enum name="fit" value="0"/>
<enum name="fixed_width" value="1"/>
<enum name="fixed_height" value="2"/>
</attr>
<!-- Must be kept in sync with SimpleExoPlayerView -->
<attr name="surface_type" format="enum">
<enum name="none" value="0"/>
<enum name="surface_view" value="1"/>
<enum name="texture_view" value="2"/>
</attr>
<attr name="show_timeout" format="integer"/>
<attr name="rewind_increment" format="integer"/>
<attr name="fastforward_increment" format="integer"/>
<attr name="player_layout_id" format="reference"/>
<attr name="controller_layout_id" format="reference"/>
<declare-styleable name="SimpleExoPlayerView">
<attr name="use_artwork" format="boolean"/>
<attr name="use_controller" format="boolean"/>
<attr name="use_texture_view" format="boolean"/>
<attr name="surface_type"/>
<attr name="show_timeout"/>
<attr name="rewind_increment"/>
<attr name="fastforward_increment"/>
<attr name="resize_mode"/>
<attr name="player_layout_id"/>
<attr name="controller_layout_id"/>
</declare-styleable>

View File

@ -14,6 +14,12 @@
limitations under the License.
-->
<resources>
<item name="exo_video_frame" type="id"/>
<item name="exo_shutter" type="id"/>
<item name="exo_subtitles" type="id"/>
<item name="exo_artwork" type="id"/>
<item name="exo_controller_placeholder" type="id"/>
<item name="exo_controller" type="id"/>
<item name="exo_play" type="id"/>
<item name="exo_pause" type="id"/>
<item name="exo_rew" type="id"/>