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