1*30877f79SAndroid Build Coastguard Worker---
2*30877f79SAndroid Build Coastguard Workertitle: UI components
3*30877f79SAndroid Build Coastguard Worker---
4*30877f79SAndroid Build Coastguard Worker
5*30877f79SAndroid Build Coastguard WorkerAn app playing media requires user interface components for displaying media and
6*30877f79SAndroid Build Coastguard Workercontrolling playback. The ExoPlayer library includes a UI module that contains
7*30877f79SAndroid Build Coastguard Workera number of UI components. To depend on the UI module add a dependency as shown
8*30877f79SAndroid Build Coastguard Workerbelow.
9*30877f79SAndroid Build Coastguard Worker
10*30877f79SAndroid Build Coastguard Worker~~~
11*30877f79SAndroid Build Coastguard Workerimplementation 'com.google.android.exoplayer:exoplayer-ui:2.X.X'
12*30877f79SAndroid Build Coastguard Worker~~~
13*30877f79SAndroid Build Coastguard Worker{: .language-gradle}
14*30877f79SAndroid Build Coastguard Worker
15*30877f79SAndroid Build Coastguard WorkerThe most important components are `StyledPlayerControlView`, `StyledPlayerView`,
16*30877f79SAndroid Build Coastguard Worker`PlayerControlView` and `PlayerView`. The styled variants provide a more
17*30877f79SAndroid Build Coastguard Workerpolished user experience, however are harder to customize.
18*30877f79SAndroid Build Coastguard Worker
19*30877f79SAndroid Build Coastguard Worker* [`StyledPlayerControlView`][] and [`PlayerControlView`][] are views for
20*30877f79SAndroid Build Coastguard Worker  controlling playbacks. They display standard playback controls including a
21*30877f79SAndroid Build Coastguard Worker  play/pause button, fast-forward and rewind buttons, and a seek bar.
22*30877f79SAndroid Build Coastguard Worker* [`StyledPlayerView`][] and [`PlayerView`][] are high level views for
23*30877f79SAndroid Build Coastguard Worker  playbacks. They display video, subtitles and album art during playback, as
24*30877f79SAndroid Build Coastguard Worker  well as playback controls using a `StyledPlayerControlView` or
25*30877f79SAndroid Build Coastguard Worker  `PlayerControlView` respectively.
26*30877f79SAndroid Build Coastguard Worker
27*30877f79SAndroid Build Coastguard WorkerAll four views have a `setPlayer` method for attaching and detaching (by passing
28*30877f79SAndroid Build Coastguard Worker`null`) player instances.
29*30877f79SAndroid Build Coastguard Worker
30*30877f79SAndroid Build Coastguard Worker## Player views ##
31*30877f79SAndroid Build Coastguard Worker
32*30877f79SAndroid Build Coastguard Worker`StyledPlayerView` and `PlayerView` can be used for both video and audio
33*30877f79SAndroid Build Coastguard Workerplaybacks. They render video and subtitles in the case of video playback, and
34*30877f79SAndroid Build Coastguard Workercan display artwork included as metadata in audio files. You can include them in
35*30877f79SAndroid Build Coastguard Workeryour layout files like any other UI component. For example, a `StyledPlayerView`
36*30877f79SAndroid Build Coastguard Workercan be included with the following XML:
37*30877f79SAndroid Build Coastguard Worker
38*30877f79SAndroid Build Coastguard Worker~~~
39*30877f79SAndroid Build Coastguard Worker<com.google.android.exoplayer2.ui.StyledPlayerView
40*30877f79SAndroid Build Coastguard Worker    android:id="@+id/player_view"
41*30877f79SAndroid Build Coastguard Worker    android:layout_width="match_parent"
42*30877f79SAndroid Build Coastguard Worker    android:layout_height="match_parent"
43*30877f79SAndroid Build Coastguard Worker    app:show_buffering="when_playing"
44*30877f79SAndroid Build Coastguard Worker    app:show_shuffle_button="true"/>
45*30877f79SAndroid Build Coastguard Worker~~~
46*30877f79SAndroid Build Coastguard Worker{: .language-xml}
47*30877f79SAndroid Build Coastguard Worker
48*30877f79SAndroid Build Coastguard WorkerThe snippet above illustrates that `StyledPlayerView` provides several
49*30877f79SAndroid Build Coastguard Workerattributes. These attributes can be used to customize the view's behavior, as
50*30877f79SAndroid Build Coastguard Workerwell as its look and feel. Most of these attributes have corresponding setter
51*30877f79SAndroid Build Coastguard Workermethods, which can be used to customize the view at runtime. The
52*30877f79SAndroid Build Coastguard Worker[`StyledPlayerView`][] Javadoc lists these attributes and setter methods in
53*30877f79SAndroid Build Coastguard Workermore detail. [`PlayerView`][] defines similar attributes.
54*30877f79SAndroid Build Coastguard Worker
55*30877f79SAndroid Build Coastguard WorkerOnce the view is declared in the layout file, it can be looked up in the
56*30877f79SAndroid Build Coastguard Worker`onCreate` method of the activity:
57*30877f79SAndroid Build Coastguard Worker
58*30877f79SAndroid Build Coastguard Worker~~~
59*30877f79SAndroid Build Coastguard Worker@Override
60*30877f79SAndroid Build Coastguard Workerprotected void onCreate(Bundle savedInstanceState) {
61*30877f79SAndroid Build Coastguard Worker  super.onCreate(savedInstanceState);
62*30877f79SAndroid Build Coastguard Worker  // ...
63*30877f79SAndroid Build Coastguard Worker  playerView = findViewById(R.id.player_view);
64*30877f79SAndroid Build Coastguard Worker}
65*30877f79SAndroid Build Coastguard Worker~~~
66*30877f79SAndroid Build Coastguard Worker{: .language-java}
67*30877f79SAndroid Build Coastguard Worker
68*30877f79SAndroid Build Coastguard WorkerWhen a player has been initialized, it can be attached to the view by calling
69*30877f79SAndroid Build Coastguard Worker`setPlayer`:
70*30877f79SAndroid Build Coastguard Worker
71*30877f79SAndroid Build Coastguard Worker~~~
72*30877f79SAndroid Build Coastguard Worker// Instantiate the player.
73*30877f79SAndroid Build Coastguard Workerplayer = new ExoPlayer.Builder(context).build();
74*30877f79SAndroid Build Coastguard Worker// Attach player to the view.
75*30877f79SAndroid Build Coastguard WorkerplayerView.setPlayer(player);
76*30877f79SAndroid Build Coastguard Worker// Set the media item to be played.
77*30877f79SAndroid Build Coastguard Workerplayer.setMediaItem(mediaItem);
78*30877f79SAndroid Build Coastguard Worker// Prepare the player.
79*30877f79SAndroid Build Coastguard Workerplayer.prepare();
80*30877f79SAndroid Build Coastguard Worker~~~
81*30877f79SAndroid Build Coastguard Worker{: .language-java}
82*30877f79SAndroid Build Coastguard Worker
83*30877f79SAndroid Build Coastguard Worker### Choosing a surface type ###
84*30877f79SAndroid Build Coastguard Worker
85*30877f79SAndroid Build Coastguard WorkerThe `surface_type` attribute of `StyledPlayerView` and `PlayerView` lets you set
86*30877f79SAndroid Build Coastguard Workerthe type of surface used for video playback. Besides the values
87*30877f79SAndroid Build Coastguard Worker`spherical_gl_surface_view` (which is a special value for spherical video
88*30877f79SAndroid Build Coastguard Workerplayback) and `video_decoder_gl_surface_view` (which is for video rendering
89*30877f79SAndroid Build Coastguard Workerusing extension renderers), the allowed values are `surface_view`,
90*30877f79SAndroid Build Coastguard Worker`texture_view` and `none`. If the view is for audio playback only, `none` should
91*30877f79SAndroid Build Coastguard Workerbe used to avoid having to create a surface, since doing so can be expensive.
92*30877f79SAndroid Build Coastguard Worker
93*30877f79SAndroid Build Coastguard WorkerIf the view is for regular video playback then `surface_view` or `texture_view`
94*30877f79SAndroid Build Coastguard Workershould be used. `SurfaceView` has a number of benefits over `TextureView` for
95*30877f79SAndroid Build Coastguard Workervideo playback:
96*30877f79SAndroid Build Coastguard Worker
97*30877f79SAndroid Build Coastguard Worker* Significantly lower power consumption on many devices.
98*30877f79SAndroid Build Coastguard Worker* More accurate frame timing, resulting in smoother video playback.
99*30877f79SAndroid Build Coastguard Worker* Support for secure output when playing DRM protected content.
100*30877f79SAndroid Build Coastguard Worker* The ability to render video content at the full resolution of the display on
101*30877f79SAndroid Build Coastguard Worker  Android TV devices that upscale the UI layer.
102*30877f79SAndroid Build Coastguard Worker
103*30877f79SAndroid Build Coastguard Worker`SurfaceView` should therefore be preferred over `TextureView` where possible.
104*30877f79SAndroid Build Coastguard Worker`TextureView` should be used only if `SurfaceView` does not meet your needs. One
105*30877f79SAndroid Build Coastguard Workerexample is where smooth animations or scrolling of the video surface is required
106*30877f79SAndroid Build Coastguard Workerprior to Android N, as described below. For this case, it's preferable to use
107*30877f79SAndroid Build Coastguard Worker`TextureView` only when [`SDK_INT`][] is less than 24 (Android N) and
108*30877f79SAndroid Build Coastguard Worker`SurfaceView` otherwise.
109*30877f79SAndroid Build Coastguard Worker
110*30877f79SAndroid Build Coastguard Worker`SurfaceView` rendering wasn't properly synchronized with view animations until
111*30877f79SAndroid Build Coastguard WorkerAndroid N. On earlier releases this could result in unwanted effects when a
112*30877f79SAndroid Build Coastguard Worker`SurfaceView` was placed into scrolling container, or when it was subjected to
113*30877f79SAndroid Build Coastguard Workeranimation. Such effects included the view's contents appearing to lag slightly
114*30877f79SAndroid Build Coastguard Workerbehind where it should be displayed, and the view turning black when subjected
115*30877f79SAndroid Build Coastguard Workerto animation. To achieve smooth animation or scrolling of video prior to Android
116*30877f79SAndroid Build Coastguard WorkerN, it's therefore necessary to use `TextureView` rather than `SurfaceView`.
117*30877f79SAndroid Build Coastguard Worker{:.info}
118*30877f79SAndroid Build Coastguard Worker
119*30877f79SAndroid Build Coastguard WorkerSome Android TV devices run their UI layer at a resolution that's lower than the
120*30877f79SAndroid Build Coastguard Workerfull resolution of the display, upscaling it for presentation to the user. For
121*30877f79SAndroid Build Coastguard Workerexample, the UI layer may be run at 1080p on an Android TV that has a 4K
122*30877f79SAndroid Build Coastguard Workerdisplay. On such devices, `SurfaceView` must be used to render content at the
123*30877f79SAndroid Build Coastguard Workerfull resolution of the display. The full resolution of the display (in its
124*30877f79SAndroid Build Coastguard Workercurrent display mode) can be queried using [`Util.getCurrentDisplayModeSize`][].
125*30877f79SAndroid Build Coastguard WorkerThe UI layer resolution can be queried using Android's [`Display.getSize`] API.
126*30877f79SAndroid Build Coastguard Worker{:.info}
127*30877f79SAndroid Build Coastguard Worker
128*30877f79SAndroid Build Coastguard Worker## Player control views ##
129*30877f79SAndroid Build Coastguard Worker
130*30877f79SAndroid Build Coastguard WorkerWhen using `StyledPlayerView`, a `StyledPlayerControlView` is used internally to
131*30877f79SAndroid Build Coastguard Workerprovide playback controls. When using a `PlayerView`, a `PlayerControlView` is
132*30877f79SAndroid Build Coastguard Workerused internally.
133*30877f79SAndroid Build Coastguard Worker
134*30877f79SAndroid Build Coastguard WorkerFor specific use cases `StyledPlayerControlView` and `PlayerControlView` can
135*30877f79SAndroid Build Coastguard Workeralso be used as standalone components. They can be included in your layout file
136*30877f79SAndroid Build Coastguard Workeras normal. For example:
137*30877f79SAndroid Build Coastguard Worker
138*30877f79SAndroid Build Coastguard Worker~~~
139*30877f79SAndroid Build Coastguard Worker<com.google.android.exoplayer2.ui.StyledPlayerControlView
140*30877f79SAndroid Build Coastguard Worker    android:id="@+id/player_control_view"
141*30877f79SAndroid Build Coastguard Worker    android:layout_width="match_parent"
142*30877f79SAndroid Build Coastguard Worker    android:layout_height="match_parent"/>
143*30877f79SAndroid Build Coastguard Worker~~~
144*30877f79SAndroid Build Coastguard Worker{: .language-xml}
145*30877f79SAndroid Build Coastguard Worker
146*30877f79SAndroid Build Coastguard WorkerThe [`StyledPlayerControlView`][] and [`PlayerControlView`][] Javadoc list the
147*30877f79SAndroid Build Coastguard Workerthe available attributes and setter methods for these components. Looking them
148*30877f79SAndroid Build Coastguard Workerup and attaching the player is similar to the example above:
149*30877f79SAndroid Build Coastguard Worker
150*30877f79SAndroid Build Coastguard Worker~~~
151*30877f79SAndroid Build Coastguard Worker@Override
152*30877f79SAndroid Build Coastguard Workerprotected void onCreate(Bundle savedInstanceState) {
153*30877f79SAndroid Build Coastguard Worker  super.onCreate(savedInstanceState);
154*30877f79SAndroid Build Coastguard Worker  // ...
155*30877f79SAndroid Build Coastguard Worker  playerControlView = findViewById(R.id.player_control_view);
156*30877f79SAndroid Build Coastguard Worker}
157*30877f79SAndroid Build Coastguard Worker
158*30877f79SAndroid Build Coastguard Workerprivate void initializePlayer() {
159*30877f79SAndroid Build Coastguard Worker  // Instantiate the player.
160*30877f79SAndroid Build Coastguard Worker  player = new ExoPlayer.Builder(context).build();
161*30877f79SAndroid Build Coastguard Worker  // Attach player to the view.
162*30877f79SAndroid Build Coastguard Worker  playerControlView.setPlayer(player);
163*30877f79SAndroid Build Coastguard Worker  // Set the media item to be played.
164*30877f79SAndroid Build Coastguard Worker  player.setMediaItem(mediaItem);
165*30877f79SAndroid Build Coastguard Worker  // Prepare the player.
166*30877f79SAndroid Build Coastguard Worker  player.prepare();
167*30877f79SAndroid Build Coastguard Worker}
168*30877f79SAndroid Build Coastguard Worker~~~
169*30877f79SAndroid Build Coastguard Worker{: .language-java}
170*30877f79SAndroid Build Coastguard Worker
171*30877f79SAndroid Build Coastguard Worker## Customization ##
172*30877f79SAndroid Build Coastguard Worker
173*30877f79SAndroid Build Coastguard WorkerWhere significant customization is required, we expect that app developers will
174*30877f79SAndroid Build Coastguard Workerimplement their own UI components rather than using those provided by
175*30877f79SAndroid Build Coastguard WorkerExoPlayer's UI module. That said, the provided UI components do allow for
176*30877f79SAndroid Build Coastguard Workercustomization by setting attributes (as described above), overriding drawables,
177*30877f79SAndroid Build Coastguard Workeroverriding layout files, and by specifying custom layout files.
178*30877f79SAndroid Build Coastguard Worker
179*30877f79SAndroid Build Coastguard Worker### Overriding drawables ###
180*30877f79SAndroid Build Coastguard Worker
181*30877f79SAndroid Build Coastguard WorkerThe drawables used by `StyledPlayerControlView` and `PlayerControlView`
182*30877f79SAndroid Build Coastguard Worker(with their default layout files) can be overridden by drawables with the same
183*30877f79SAndroid Build Coastguard Workernames defined in your application. See the [`StyledPlayerControlView`][] and
184*30877f79SAndroid Build Coastguard Worker[`PlayerControlView`][] Javadoc for a list of drawables that can be overridden.
185*30877f79SAndroid Build Coastguard WorkerNote that overriding these drawables will also affect the appearance of
186*30877f79SAndroid Build Coastguard Worker`PlayerView` and `StyledPlayerView`, since they use these views internally.
187*30877f79SAndroid Build Coastguard Worker
188*30877f79SAndroid Build Coastguard Worker### Overriding layout files ###
189*30877f79SAndroid Build Coastguard Worker
190*30877f79SAndroid Build Coastguard WorkerAll of the view components inflate their layouts from corresponding layout
191*30877f79SAndroid Build Coastguard Workerfiles, which are specified in their Javadoc. For example when a
192*30877f79SAndroid Build Coastguard Worker`PlayerControlView` is instantiated, it inflates its layout from
193*30877f79SAndroid Build Coastguard Worker`exo_player_control_view.xml`. To customize these layouts, an application
194*30877f79SAndroid Build Coastguard Workercan define layout files with the same names in its own `res/layout*`
195*30877f79SAndroid Build Coastguard Workerdirectories. These layout files will override the ones provided by the ExoPlayer
196*30877f79SAndroid Build Coastguard Workerlibrary.
197*30877f79SAndroid Build Coastguard Worker
198*30877f79SAndroid Build Coastguard WorkerAs an example, suppose we want our playback controls to consist of only a
199*30877f79SAndroid Build Coastguard Workerplay/pause button positioned in the center of the view. We can achieve this by
200*30877f79SAndroid Build Coastguard Workercreating an `exo_player_control_view.xml` file in the application’s
201*30877f79SAndroid Build Coastguard Worker`res/layout` directory, containing:
202*30877f79SAndroid Build Coastguard Worker
203*30877f79SAndroid Build Coastguard Worker~~~
204*30877f79SAndroid Build Coastguard Worker<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
205*30877f79SAndroid Build Coastguard Worker    android:layout_width="match_parent"
206*30877f79SAndroid Build Coastguard Worker    android:layout_height="match_parent">
207*30877f79SAndroid Build Coastguard Worker
208*30877f79SAndroid Build Coastguard Worker  <ImageButton android:id="@id/exo_play"
209*30877f79SAndroid Build Coastguard Worker      android:layout_width="100dp"
210*30877f79SAndroid Build Coastguard Worker      android:layout_height="100dp"
211*30877f79SAndroid Build Coastguard Worker      android:layout_gravity="center"
212*30877f79SAndroid Build Coastguard Worker      android:background="#CC000000"
213*30877f79SAndroid Build Coastguard Worker      style="@style/ExoMediaButton.Play"/>
214*30877f79SAndroid Build Coastguard Worker
215*30877f79SAndroid Build Coastguard Worker  <ImageButton android:id="@id/exo_pause"
216*30877f79SAndroid Build Coastguard Worker      android:layout_width="100dp"
217*30877f79SAndroid Build Coastguard Worker      android:layout_height="100dp"
218*30877f79SAndroid Build Coastguard Worker      android:layout_gravity="center"
219*30877f79SAndroid Build Coastguard Worker      android:background="#CC000000"
220*30877f79SAndroid Build Coastguard Worker      style="@style/ExoMediaButton.Pause"/>
221*30877f79SAndroid Build Coastguard Worker
222*30877f79SAndroid Build Coastguard Worker</FrameLayout>
223*30877f79SAndroid Build Coastguard Worker~~~
224*30877f79SAndroid Build Coastguard Worker{: .language-xml}
225*30877f79SAndroid Build Coastguard Worker
226*30877f79SAndroid Build Coastguard WorkerThe change in visual appearance compared to the standard controls is shown
227*30877f79SAndroid Build Coastguard Workerbelow.
228*30877f79SAndroid Build Coastguard Worker
229*30877f79SAndroid Build Coastguard Worker{% include figure.html url="/images/overriding-layoutfiles.png" index="1" caption="Replacing the standard playback controls (left) with custom controls (right)" %}
230*30877f79SAndroid Build Coastguard Worker
231*30877f79SAndroid Build Coastguard Worker### Custom layout files ###
232*30877f79SAndroid Build Coastguard Worker
233*30877f79SAndroid Build Coastguard WorkerOverriding a layout file is an excellent solution for changing the layout across
234*30877f79SAndroid Build Coastguard Workerthe whole of an application, but what if a custom layout is required only in a
235*30877f79SAndroid Build Coastguard Workersingle place? To achieve this, first define a layout file as though overriding
236*30877f79SAndroid Build Coastguard Workerone of the default layouts, but this time giving it a different file name, for
237*30877f79SAndroid Build Coastguard Workerexample `custom_controls.xml`. Second, use an attribute to indicate that this
238*30877f79SAndroid Build Coastguard Workerlayout should be used when inflating the view. For example when using
239*30877f79SAndroid Build Coastguard Worker`PlayerView`, the layout inflated to provide the playback controls can be
240*30877f79SAndroid Build Coastguard Workerspecified using the `controller_layout_id` attribute:
241*30877f79SAndroid Build Coastguard Worker
242*30877f79SAndroid Build Coastguard Worker~~~
243*30877f79SAndroid Build Coastguard Worker<com.google.android.exoplayer2.ui.PlayerView android:id="@+id/player_view"
244*30877f79SAndroid Build Coastguard Worker     android:layout_width="match_parent"
245*30877f79SAndroid Build Coastguard Worker     android:layout_height="match_parent"
246*30877f79SAndroid Build Coastguard Worker     app:controller_layout_id="@layout/custom_controls"/>
247*30877f79SAndroid Build Coastguard Worker~~~
248*30877f79SAndroid Build Coastguard Worker{: .language-xml}
249*30877f79SAndroid Build Coastguard Worker
250*30877f79SAndroid Build Coastguard Worker[`PlayerView`]: {{ site.exo_sdk }}/ui/PlayerView.html
251*30877f79SAndroid Build Coastguard Worker[`PlayerControlView`]: {{ site.exo_sdk }}/ui/PlayerControlView.html
252*30877f79SAndroid Build Coastguard Worker[`StyledPlayerView`]: {{ site.exo_sdk }}/ui/StyledPlayerView.html
253*30877f79SAndroid Build Coastguard Worker[`StyledPlayerControlView`]: {{ site.exo_sdk }}/ui/StyledPlayerControlView.html
254*30877f79SAndroid Build Coastguard Worker[`SDK_INT`]: {{ site.android_sdk }}/android/os/Build.VERSION.html#SDK_INT
255*30877f79SAndroid Build Coastguard Worker[`Util.getCurrentDisplayModeSize`]: {{ site.exo_sdk }}/util/Util.html#getCurrentDisplayModeSize(android.content.Context)
256*30877f79SAndroid Build Coastguard Worker[`Display.getSize`]: {{ site.android_sdk }}/android/view/Display.html#getSize(android.graphics.Point)
257