Download the complete source code for this project:
- as a ZIP file
- view on Github
ExoPlayer is a great alternative to Android’s MediaPlayer API and adds support for HLS, DASH, and SmoothStreaming adaptive playback. While it is far superior to Android’s default media player, it lacks the ability to easily toggle a video in and out of a full screen mode. Today I’ll show you a solution to this problem.
Expand! Shrink!
Rather than creating a new activity, this solution uses the magic of a fullscreen dialog. When the video is toggled into fullscreen mode, the SimpleExoPlayerView
will be removed from the activity layout, and added to a new dialog. The transition between views is very fast, and there is no audio stuttering or buffering when streaming video.
The XML
First we’ll add the fullscreen toggle button to the Exoplayer controls. This can be done by overriding the default PlaybackControlView
layout. To do this, copy the exo_playback_control_view.xml file from the exoplayer-ui package into your project’s layout directory. You’ll also want some image assets to use for the expand and shrink icons. You can download the icons used in this example here:
– ic_fullscreen_expand.png | |
– ic_fullscreen_shrink.png |
Ideally, you’d want different sized images for different screen densities, but for this example you can just copy these assets into your project’s drawable directory.
Next, we’ll edit the exo_playback_control_view.xml
file. Add the following to the second horizontal LinearLayout
. This code should go towards the bottom of the file, after the exo_duration
TextView
and before the second-to-last closing </LinearLayout>
tag:
<FrameLayout android:id="@+id/exo_fullscreen_button" android:layout_width="32dp" android:layout_height="32dp" android:layout_gravity="right"> <ImageView android:id="@+id/exo_fullscreen_icon" android:layout_width="18dp" android:layout_height="18dp" android:layout_gravity="center" android:adjustViewBounds="true" android:scaleType="fitCenter" android:src="@drawable/ic_fullscreen_expand"/> </FrameLayout>
Add The Controller Id
Now copy the exo_simple_player_view.xml file into your project’s layout directory. Add the following towards the bottom of the file, between the exo_controller_placeholder
View and the exo_overlay
FrameLayout:
<com.google.android.exoplayer2.ui.PlaybackControlView android:id="@id/exo_controller" android:layout_width="match_parent" android:layout_height="match_parent" />
This step is necessary in order to get a reference to the PlayBackControlView
from our activity by calling findViewById on the SimpleExoPlayerView
object (more on this later.)
Add The Player View To MainActivity’s Layout
To finish up the XML, we’ll add SimpleExoPlayerView to our activity. Inside of activity_main.xml, add the following:
<FrameLayout android:id="@+id/main_media_frame" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000000"> <com.google.android.exoplayer2.ui.SimpleExoPlayerView android:id="@+id/exoplayer" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" /> </FrameLayout>
Adjust the FrameLayout’s width and height to your liking. The sample project assigns the layout a height of 0dp with a weight of 0.5 so it will fill half of the screen.
We wrap the SimpleExoPlayerView in a FrameLayout so that the view can be removed and re-added when the video is toggled in and out of full screen.
The Java
Ok, onto the Java code. Create a Dialog member variable called mFullScreenDialog. When initializing it, override the dialog’s onBackPressed() method:
private void initFullscreenDialog() { mFullScreenDialog = new Dialog(this, android.R.style.Theme_Black_NoTitleBar_Fullscreen) { public void onBackPressed() { if (mExoPlayerFullscreen) closeFullscreenDialog(); super.onBackPressed(); } }; }
This allows the user to exit fullscreen mode by either pressing the shrink button in the lower right of their screen, or by using their device’s back button. Also notice that we passed the android.R.style.Theme_Black_NoTitleBar_Fullscreen
style into the dialog’s constructor. This will make the dialog fill the entire screen when it’s shown.
Entering Fullscreen
Next, create a method called openFullscreenDialog()
. This method programmatically removes the SimpleExoPlayerView from the activity, adds a new instance of the view to the fullscreen dialog, and shows the dialog:
private void openFullscreenDialog() { ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView); mFullScreenDialog.addContentView(mExoPlayerView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fullscreen_skrink)); mExoPlayerFullscreen = true; mFullScreenDialog.show(); }
Exiting Fullscreen
Now create a method called closeFullscreenDialog()
. This method adds a new SimpleExoPlayerView to the activity, removes the view from the fullscreen dialog, and dismisses the dialog:
private void closeFullscreenDialog() { ((ViewGroup) mExoPlayerView.getParent()).removeView(mExoPlayerView); ((FrameLayout) findViewById(R.id.main_media_frame)).addView(mExoPlayerView); mExoPlayerFullscreen = false; mFullScreenDialog.dismiss(); mFullScreenIcon.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fullscreen_expand)); }
Initializing The Fullscreen Button
Finally, create a method to initialize the fullscreen button. In order to get a reference to the button, we first need a reference to the player’s PlaybackControlView. To do this, we call mExoPlayerView.findViewById(R.id.exo_controller)
. We added a view with this id earlier to exo_simple_player_view.xml
.
private void initFullscreenButton() { PlaybackControlView controlView = mExoPlayerView.findViewById(R.id.exo_controller); mFullScreenIcon = controlView.findViewById(R.id.exo_fullscreen_icon); mFullScreenButton = controlView.findViewById(R.id.exo_fullscreen_button); mFullScreenButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!mExoPlayerFullscreen) openFullscreenDialog(); else closeFullscreenDialog(); } }); }
To understand why a view with this specific id is necessary, we can take a look at the source code of SimpleExoPlayerView
. Inside the view’s constructor we see the following:
PlaybackControlView customController = (PlaybackControlView) findViewById(R.id.exo_controller); ... if (customController != null) { this.controller = customController; } ... else { this.controller = null; }
If this id isn’t found, the PlaybackControlView is created elsewhere programmatically.
That’s It!
That should be everything you need to add a fullscreen mode to an existing Exoplayer implementation. If you need further examples of how to initialize Exoplayer and tie everything together, you can view the complete source code for the activity here, or download the complete project on GitHub.
Nite
Hi,
I have problems with playing mp4 video when switch to fullscreen/normal, start buffering and play video from start. For mp4 video i use ExtractorMediaSource.
Thanks
Tanat29
Thanks for good content
Lee Yong
Great!
Very Great!
You are brilliant DEVELOPER
From beauty_rabbit
subhanjan
working if the player is in main activity. But when I place this code and use the exoplayer in another activity I get the error cannot change view. for custom activity, what code should I use?
Geoff Ledak
It should work the same regardless if you’re working with the launcher activity or not.
Can you post your code somewhere, or the specific error messages you’re getting?
Balu Sonawane
Working Very Vell……
You solved my problem , Thanks for this tutorial.
rajjan sharma
can you give the source code please
email – rajjansharma669@gmail.com
Mansi
Thanks for a great working example.
I was able to implement this and it work flawlessly for the most part but I see a little bit of a lag when switching from fullscreen mode to small screen mode and vice versa.
The only glaring difference between my code and yours is the I’m using ExtractorMediaSource for an mp4 file.
Any pointers on how I can avoid the lag/latency? Thanks!
Geoff Ledak
Hey Mansi,
I haven’t tried using an ExtractorMediaSource but I’ll try it tonight. What kind of phone are using? Does it lag when running on an emulator?
-Geoff
Mansi
I’m actually using it on a FireTV device. It lags on both the emulator and the TV itself.
There’s, maybe, half a second delay before the video continues to play – its not seamless.
Mansi
And the interesting part is: there is no lag in audio. The lag is only seen in video. So while the audio continues to play, the video is stuck for half a second before it catches up with the audio!
Leonard
Hi, Geoff,
This is a great solution, however, it seems only works under same screen orientation? Could you share some opinion to implement the full screen like youtube does?
Geoff Ledak
Hey Leonard,
Device rotation will work with this solution.
If you wanted to force the app into landscape mode when the video is set to fullscreen like the youtube app does, I believe you could add setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); inside the openFullscreenDialog() method and setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); inside the closeFullscreenDialog() method.
Cheers!
-Geoff
JRB
Hey Geoff,
You are a Life saver bud, thanks for the tutorial. Also I wanted to know if we can add Variable speed playback options to the same tutorial. Can you give it a look? Also, there is a small lag in the video when changing the orientation from Portrait to Landscape or from Landscape to Portrait.
Harsh Masand
Did you find anything to solve it??
Darian
Geoff, your tutorial works when the activity starts on portrait but when the activity starts on landscape and try to exit full screen the app stop woking. Any suggestions???
mitesh viradiya
Hello,
I would like to say thank you very much for such a good solution with example. its too much help full for me.
I have one problem, I am using your method for full screen functionality and its work fine but when I use my custom control for exoplayer (i.e. app:controller_layout_id=”@layout/exoplayer_controls”) i use it for achieving thumbnail image when timebar event done by the user.
Here it work fine while in normal screen but while i start full screen dialog than change the video position it dose not load the image even method was called for thumbnail
hiddeneyes02
Thank you for the great tutorial
One point though: PlaybackControlView controlView = mExoPlayerView.findViewById(R.id.exo_controller);
This is depreacated, I used findViewById directly on your my SimpleExoPlayerView
Exoplayerのコントローラーに全画面表示のアイコンを入れてみよう - YUEDY
[…] How to Add a Fullscreen Toggle Button to ExoPlayer in Android […]
Mathi
When switching from small screen to fullscreen the video stucks for some time and then resumes. How can i make the transition smooth.
Abhishek Kumar
This only works for one orientation mode. How can I open the dialog in landscape mode when fullscreen button is clicked?
The above way is very good when you want both your half screen exoplayer and fullscreen exoplayer in the same orientation. Any way we can go with this approach for changing the orientation?
Geoff Ledak
Hi Abhishek,
I haven’t tried it, but if you want to force the app into landscape mode when the video is set to fullscreen, I believe you could add setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); inside the openFullscreenDialog() method and setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); inside the closeFullscreenDialog() method.
-Geoff
Debashish Dey
Hi Geoff Ledak,
Tried setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) which causes the dialog to disappear. Please, can you tell me how to implement it correctly? Thanks
strike back
Nice programming style 🙂
Solved a few of my problems, namely:
1) of course the fullscreen thing…
2)adding custom layout elements to my Exoplayer (2 buttons)
to be able to speed up/slow down the playback by hitting them.
so thanks!
Best regards, Lukas
Geoff Ledak
Thanks! Glad I could help.
Nadeem Ahmad
hi sir please add ProgressBar this code please
pleace ProgressBar add this code
Dhaval
This is a great tutorial for implement a video player in android
but i have confusion basically i am develop a android app for tv ,when i test the app in mobile device it’s working fine, but when i am run the app on android tv emulator it’s not working
Amin Idrissi
Please Bro, Help Me ! Can I chat with you in Messenger ?
Benjamin
Thank you for this wonderful tutorial. Please i have problem on orientation change, the video starts all over again. I’m using exoplayer 2.8.4 and one thing i discovered is that in the initPlayer(), mExoPlayerView.getPlayer().prepare(mVideoSource);
prepare cannot be resolved so i used player.prepare(mVideoSource); could this be the reason my videos are starting all over again on orientation change and if so please how can I solve this. Thank you in advance.
Web Dev
Dude! you are a gem.
Thank you
boekhouder breda
Have you ever thought about creating an ebook or guest authoring on other
blogs? I have a blog based on the same subjects you discuss and would really like to have you share some stories/information. I know my audience would appreciate
your work. If you are even remotely interested, feel free to
send me an e mail.
Waseef Akhtar
Has anyone experienced this after following the tutorial? https://stackoverflow.com/questions/58647107/video-stretches-and-rotates-when-fullscreen-is-tapped-in-exoplayer
Lanette Hinman
Pretty! This has been a really wonderful article. Many thanks for providing this information.|