Full screen button android

Fullscreen functionality with Android ExoPlayer

ExoPlayer is a great Android library that deals with a lot of the pains you might encounter when trying to stream video. However, unless the video you’re playing is being displayed in a fullscreen Activity by default this can cause some issues when it comes to smooth playback.

You may find that the audio will keep playing while the video hangs waiting to resync with the audio, or that when you go back to the calling activity the video has now gone blank but still responds to input.

As much as I tried to find a good solution on StackOverflow and other sources on the internet, I just couldn’t. After approaching this problem from various angles. Here is a nice, reliable solution that I came up with:

This class uses the Singleton Design Pattern to ensure there always only one instance in the app as we’re only interested in the playback of one video. If you want to do multiple videos at the same time look at keeping references to each instance of this class instead.

After we have got the refernce to the current instance of the ExoPlayerVideoHandler we then prepare the SimpleExoPlayerView of the parent activity to play the video from the URI.

If the player variable is null or the URI does not match the previously stored URI than we want to play a new video and re-run the code required to setup ExoPlayer. Otherwise, we want to reset the video surface (this prevents the screen from being blank when going back to an activity) and reset the position of the player to it’s current position. (The +1 also forces a re-draw by buffering the video).

goToBackground and goToForeground are 2 helper methods that ensure that the video state is kept when switching between activities (namely the parent Activity and the video’s fullscreen Activity) and will continue playing or stay paused.

Used in practice the code looks something like this:

The view is found and set to the ExoPlayer instance created inside the ExoPlayerVideoHandler. When the activity is paused the player goes to the background and when the activity is destroyed the player is released.

An OnClickListener is also added to the SimpleExoPlayerView’s added fullscreen button. This fires off an intent to the FullscreenVideoActivity. The code of which looks like this:

This Activity gets the existing instance of the player from the ExoPlayerVideoHandler and brings it back to the foreground which will continue playing the video from where the last activity was.

The destroyVideo flag determines if the entire app is being forcibly killed by the OS or if the user simply wants to stop viewing the video in fullscreen. By default the flag is true and will only be set to false if the user makes a deliberate action. Otherwise, the player will be released.

Hopefully this will help anyone out that’s also having the same issues when trying to show the same ExoPlayer video stream in different activities. Good luck!

Источник

How to Add a Fullscreen Toggle Button to ExoPlayer in Android

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.

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 tag:

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:

Читайте также:  Network signal strength android

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:

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:

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:

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:

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 .

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:

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.

33 Comments

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.

Источник

Buttons

A button consists of text or an icon (or both text and an icon) that communicates what action occurs when the user touches it.

Depending on whether you want a button with text, an icon, or both, you can create the button in your layout in three ways:

  • With text, using the Button class:
  • With an icon, using the ImageButton class:
  • With text and an icon, using the Button class with the android:drawableLeft attribute:

Key classes are the following:

Responding to Click Events

When the user clicks a button, the Button object receives an on-click event.

To define the click event handler for a button, add the android:onClick attribute to the element in your XML layout. The value for this attribute must be the name of the method you want to call in response to a click event. The Activity hosting the layout must then implement the corresponding method.

For example, here’s a layout with a button using android:onClick :

Within the Activity that hosts this layout, the following method handles the click event:

Kotlin

The method you declare in the android:onClick attribute must have a signature exactly as shown above. Specifically, the method must:

  • Be public
  • Return void
  • Define a View as its only parameter (this will be the View that was clicked)

Using an OnClickListener

You can also declare the click event handler programmatically rather than in an XML layout. This might be necessary if you instantiate the Button at runtime or you need to declare the click behavior in a Fragment subclass.

To declare the event handler programmatically, create an View.OnClickListener object and assign it to the button by calling setOnClickListener(View.OnClickListener) . For example:

Kotlin

Styling Your Button

The appearance of your button (background image and font) may vary from one device to another, because devices by different manufacturers often have different default styles for input controls.

You can control exactly how your controls are styled using a theme that you apply to your entire application. For instance, to ensure that all devices running Android 4.0 and higher use the Holo theme in your app, declare android:theme=»@android:style/Theme.Holo» in your manifest’s element. Also read the blog post, Holo Everywhere for information about using the Holo theme while supporting older devices.

To customize individual buttons with a different background, specify the android:background attribute with a drawable or color resource. Alternatively, you can apply a style for the button, which works in a manner similar to HTML styles to define multiple style properties such as the background, font, size, and others. For more information about applying styles, see Styles and Themes.

Borderless button

One design that can be useful is a «borderless» button. Borderless buttons resemble basic buttons except that they have no borders or background but still change appearance during different states, such as when clicked.

Читайте также:  Как обновить дизайн андроида

To create a borderless button, apply the borderlessButtonStyle style to the button. For example:

Custom background

If you want to truly redefine the appearance of your button, you can specify a custom background. Instead of supplying a simple bitmap or color, however, your background should be a state list resource that changes appearance depending on the button’s current state.

You can define the state list in an XML file that defines three different images or colors to use for the different button states.

To create a state list drawable for your button background:

    Create three bitmaps for the button background that represent the default, pressed, and focused button states.

To ensure that your images fit buttons of various sizes, create the bitmaps as Nine-patch bitmaps.

Источник

artemisia-absynthium / AndroidManifest.xml

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

xml version = » 1.0 » encoding = » utf-8 » ?>
FrameLayout xmlns : android = » http://schemas.android.com/apk/res/android «
xmlns : tools = » http://schemas.android.com/tools «
android : id = » @+id/enclosing_layout «
android : layout_width = » match_parent «
android : layout_height = » match_parent «
android : background = » @android:color/black «
tools : context = » .FullscreenVideoActivity » >
com .google.android.exoplayer2.ui.PlayerView
android : id = » @+id/player_view «
android : layout_width = » match_parent «
android : layout_height = » match_parent »/>
FrameLayout >

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

.
activity
android : name = » .FullscreenVideoActivity «
android : configChanges = » orientation|keyboardHidden|screenSize «
android : label = » @string/app_name «
android : theme = » @style/FullscreenTheme »/>
.

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

.
color name = » black_overlay » >#66000000 color >
.

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

xml version = » 1.0 » encoding = » utf-8 » ?>
LinearLayout xmlns : android = » http://schemas.android.com/apk/res/android «
xmlns : app = » http://schemas.android.com/apk/res-auto «
android : layout_width = » match_parent «
android : layout_height = » wrap_content «
android : layout_gravity = » bottom «
android : background = » #CC000000 «
android : layoutDirection = » ltr «
android : orientation = » vertical » >
LinearLayout
android : layout_width = » match_parent «
android : layout_height = » wrap_content «
android : gravity = » center «
android : orientation = » horizontal «
android : paddingTop = » 4dp » >
ImageButton
android : id = » @id/exo_prev «
style = » @style/ExoMediaButton.Previous »/>
ImageButton
android : id = » @id/exo_rew «
style = » @style/ExoMediaButton.Rewind »/>
ImageButton
android : id = » @id/exo_shuffle «
style = » @style/ExoMediaButton.Shuffle »/>
ImageButton
android : id = » @id/exo_repeat_toggle «
style = » @style/ExoMediaButton »/>
ImageButton
android : id = » @id/exo_play «
style = » @style/ExoMediaButton.Play »/>
ImageButton
android : id = » @id/exo_pause «
style = » @style/ExoMediaButton.Pause »/>
ImageButton
android : id = » @id/exo_ffwd «
style = » @style/ExoMediaButton.FastForward »/>
ImageButton
android : id = » @id/exo_next «
style = » @style/ExoMediaButton.Next »/>
LinearLayout >
LinearLayout
android : layout_width = » match_parent «
android : layout_height = » wrap_content «
android : layout_marginTop = » 4dp «
android : gravity = » center_vertical «
android : orientation = » horizontal » >
TextView
android : id = » @id/exo_position «
android : layout_width = » wrap_content «
android : layout_height = » wrap_content «
android : includeFontPadding = » false «
android : paddingLeft = » 4dp «
android : paddingRight = » 4dp «
android : textColor = » #FFBEBEBE «
android : textSize = » 14sp «
android : textStyle = » bold »/>
com .google.android.exoplayer2.ui.DefaultTimeBar
android : id = » @id/exo_progress «
android : layout_width = » 0dp «
android : layout_height = » 26dp «
android : layout_weight = » 1 »/>
TextView
android : id = » @id/exo_duration «
android : layout_width = » wrap_content «
android : layout_height = » wrap_content «
android : includeFontPadding = » false «
android : paddingLeft = » 4dp «
android : paddingRight = » 4dp «
android : textColor = » #FFBEBEBE «
android : textSize = » 14sp «
android : textStyle = » bold »/>
FrameLayout
android : id = » @+id/exo_fullscreen_button «
android : layout_width = » 32dp «
android : layout_height = » wrap_content «
android : layout_gravity = » right » >
ImageView
android : id = » @+id/exo_fullscreen_icon «
android : layout_width = » 40dp «
android : layout_height = » 40dp «
android : layout_gravity = » center «
android : adjustViewBounds = » true «
android : scaleType = » fitCenter «
app : srcCompat = » @drawable/ic_fullscreen »/>
FrameLayout >
LinearLayout >
LinearLayout >

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

xml version = » 1.0 » encoding = » utf-8 » ?>
merge xmlns : android = » http://schemas.android.com/apk/res/android » >
com .google.android.exoplayer2.ui.AspectRatioFrameLayout
android : id = » @id/exo_content_frame «
android : layout_width = » match_parent «
android : layout_height = » match_parent «
android : layout_gravity = » center » >
Video surface will be inserted as the first child of the content frame. —>
View
android : id = » @id/exo_shutter «
android : layout_width = » match_parent «
android : layout_height = » match_parent «
android : background = » @android:color/black »/>
ImageView
android : id = » @id/exo_artwork «
android : layout_width = » match_parent «
android : layout_height = » match_parent «
android : scaleType = » fitXY »/>
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>
FrameLayout
android : id = » @id/exo_overlay «
android : layout_width = » match_parent «
android : layout_height = » match_parent »/>
com .google.android.exoplayer2.ui.PlayerControlView
android : id = » @id/exo_controller «
android : layout_width = » match_parent «
android : layout_height = » match_parent »/>
merge >
Читайте также:  Honor 20s android pay

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

public class ExoPlayerViewManager <
private static final String TAG = » ExoPlayerViewManager » ;
public static final String EXTRA_VIDEO_URI = » video_uri » ;
private static Map String , ExoPlayerViewManager > instances = new HashMap<> ();
private Uri videoUri;
public static ExoPlayerViewManager getInstance ( String videoUri ) <
ExoPlayerViewManager instance = instances . get(videoUri);
if (instance == null ) <
instance = new ExoPlayerViewManager (videoUri);
instances . put(videoUri, instance);
>
return instance;
>
private SimpleExoPlayer player;
private boolean isPlayerPlaying;
private ExoPlayerViewManager ( String videoUri ) <
this . videoUri = Uri . parse(videoUri);
>
public void prepareExoPlayer ( Context context , PlayerView exoPlayerView ) <
if (context == null || exoPlayerView == null ) <
return ;
>
if (player == null ) <
// Create a new player if the player is null or
// we want to play a new video
// Do all the standard ExoPlayer code here.
// Prepare the player with the source.
player . prepare(videoSource);
>
player . clearVideoSurface();
player . setVideoSurfaceView(( SurfaceView ) exoPlayerView . getVideoSurfaceView());
player . seekTo(player . getCurrentPosition() + 1 );
exoPlayerView . setPlayer(player);
>
public void releaseVideoPlayer () <
if (player != null ) <
player . release();
>
player = null ;
>
public void goToBackground () <
if (player != null ) <
isPlayerPlaying = player . getPlayWhenReady();
player . setPlayWhenReady( false );
>
>
public void goToForeground () <
if (player != null ) <
player . setPlayWhenReady(isPlayerPlaying);
>
>
>

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

// Fullscreen related code taken from Android Studio blueprint
public class FullscreenVideoActivity extends AppCompatActivity <
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private static final int UI_ANIMATION_DELAY = 300 ;
private final Handler mHideHandler = new Handler ();
private View mContentView;
private final Runnable mHidePart2Runnable = new Runnable () <
@SuppressLint ( » InlinedApi » )
@Override
public void run () <
// Delayed removal of status and navigation bar
// Note that some of these constants are new as of
// API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
mContentView . setSystemUiVisibility( View . SYSTEM_UI_FLAG_LOW_PROFILE
| View . SYSTEM_UI_FLAG_FULLSCREEN
| View . SYSTEM_UI_FLAG_LAYOUT_STABLE
| View . SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View . SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View . SYSTEM_UI_FLAG_HIDE_NAVIGATION );
>
>;
private final Runnable mHideRunnable = new Runnable () <
@Override
public void run () <
hide();
>
>;
private String mVideoUri;
@Override
public void onCreate ( Bundle savedInstanceState ) <
super . onCreate(savedInstanceState);
setContentView( R . layout . activity_fullscreen_video);
mContentView = findViewById( R . id . enclosing_layout);
PlayerView playerView = findViewById( R . id . player_view);
mVideoUri = getIntent() . getStringExtra( ExoPlayerViewManager . EXTRA_VIDEO_URI );
ExoPlayerViewManager . getInstance(mVideoUri)
.prepareExoPlayer( this , playerView);
// Set the fullscreen button to «close fullscreen» icon
View controlView = playerView . findViewById( R . id . exo_controller);
ImageView fullscreenIcon = controlView . findViewById( R . id . exo_fullscreen_icon);
fullscreenIcon . setImageResource( R . drawable . exo_controls_fullscreen_exit);
controlView . findViewById( R . id . exo_fullscreen_button)
.setOnClickListener( new View . OnClickListener () <
@Override
public void onClick ( View v ) <
finish();
>
>);
>
@Override
public void onResume () <
super . onResume();
ExoPlayerViewManager . getInstance(mVideoUri) . goToForeground();
>
@Override
public void onPause () <
super . onPause();
ExoPlayerViewManager . getInstance(mVideoUri) . goToBackground();
>
@Override
public void onPostCreate ( Bundle savedInstanceState ) <
super . onPostCreate(savedInstanceState);
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
delayedHide();
>
private void hide () <
// Schedule a runnable to remove the status and navigation bar after a delay
mHideHandler . postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY );
>
/**
* Schedules a call to hide() in delay milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide () <
mHideHandler . removeCallbacks(mHideRunnable);
mHideHandler . postDelayed(mHideRunnable, 100 );
>
>

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

public class MyActivity extends AppCompatActivity <
private List String > mVideoUrls;
@Override
public void onCreate ( Bundle savedInstanceState ) <
super . onCreate(savedInstanceState);
// Your activity setup code.
for ( String videoUrl : mVideoUrls) <
setupPlayerView(videoView, videoUrl);
>
>
@Override
public void onResume () <
super . onResume();
for ( String videoUrl : mVideoUrls) <
ExoPlayerViewManager . getInstance(videoUrl) . goToForeground();
>
>
@Override
public void onPause () <
super . onPause();
for ( String videoUrl : mVideoUrls) <
ExoPlayerViewManager . getInstance(videoUrl) . goToBackground();
>
>
@Override
public void onDestroyView () <
super . onDestroyView();
for ( String videoUrl : mVideoUrls) <
ExoPlayerViewManager . getInstance(videoUrl) . releaseVideoPlayer();
>
>
private void setupPlayerView ( final PlayerView videoView , final String videoUrl ) <
ExoPlayerViewManager . getInstance(videoUrl) . prepareExoPlayer(getContext(), videoView);
ExoPlayerViewManager . getInstance(videoUrl) . goToForeground();
View controlView = videoView . findViewById( R . id . exo_controller);
controlView . findViewById( R . id . exo_fullscreen_button)
.setOnClickListener( new View . OnClickListener () <
@Override
public void onClick ( View v ) <
Intent intent = new Intent (getContext(), FullscreenVideoActivity . class);
intent . putExtra( ExoPlayerViewManager . EXTRA_VIDEO_URI , videoUrl);
getActivity() . startActivity(intent);
>
>);
>
>

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

Источник

Оцените статью