5

I'm trying to implement a full screen mode with SimpleExoPlayerView. I've got this mostly working using setSystemUiVisibility.

During onCreate i add a OnSystemUiVisibilityChange listener to sync hiding the player controls with the actionbar.

    @Override
public void onCreate(Bundle savedInstanceState) {

    View decorView = getWindow().getDecorView();
    decorView.setOnSystemUiVisibilityChangeListener
            (onSystemUiChange());

    hideSystemUI();
}

In the OnSystemUiVisibilityChangeListener i'm also setting a timeout that matches the simpleExoplayerViews timeout so the controls and action bar are hidden at the same time.

    @NonNull
private View.OnSystemUiVisibilityChangeListener onSystemUiChange() {
    return new View.OnSystemUiVisibilityChangeListener() {
        @Override
        public void onSystemUiVisibilityChange(int visibility) {
            if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                mSimpleExoPlayerView.showController();
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //sync the hide system ui with 
                        //simpleExoPlayerView's auto hide timeout
                        hideSystemUI();
                    }
                }, mSimpleExoPlayerView.getControllerShowTimeoutMs());

            } else {
                mSimpleExoPlayerView.hideController();
            }
        }
    };
}

private void hideSystemUI() {
    View rootView = findViewById(R.id.root);
    rootView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
    );
}

This works pretty well except in one case. If you tap the screen and then tap it again before the SimpleExoPlayerView controls timeout the SimpleExoPlayerView are hidden but the system ui do not get set until the timeout. Is there any events i can hook into instead?

I've tried setting a onClick and onTouch listener for my root layout but these events are not fired, i suspect SimpleExoPlayerView might be swallowing them?

Ryan Burnham
  • 573
  • 6
  • 15
  • I had the same issue. Its not related to `SimpleExoPlayerView`. The reason why `onTouch()` doesn't work is whenever `SYSTEM_UI_FLAG_FULLSCREEN` is set the first event is always captured by the [DecoreView](https://stackoverflow.com/a/23277613/1889768) and consequent events are available to other views. – Abbas Jul 10 '17 at 11:15
  • You could try show and hide with `postDelayed`. It might work or might not I never tried it. – Abbas Jul 10 '17 at 11:17
  • hmm, i'll check it out, thanks for the hints – Ryan Burnham Jul 11 '17 at 09:11

4 Answers4

8

ExoPlayer 2.10.4 has it.

exoplayer PlayerView has a method called

public void setControllerVisibilityListener(PlayerControlView.VisibilityListener listener) {
}
AndroidDev
  • 1,485
  • 2
  • 18
  • 33
1

As of 2.6.1, SimpleExoPlayerView doesn't seem to have any visibility change listeners for the controls, but PlaybackControlView has. However, it's stored in a private field in SimpleExoPlayerView and there's no builtin way to a access it. To set your own listener, you'll either have to:

  • copy SimpleExoPlayerView.java to your project and make the required changes,
  • use reflection (don't forget to add proguard rules, if needed),
  • override exo_simple_player_view.xml and make sure it contains a PlaybackControlView, then find it using findViewById,
  • find it manually by traversing the view hierarchy.

In my opinion, the first and third options are the nicest, but the last one requires the least amount of changes, and it also works very well. Here is an example:

import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;

public SomeActivity extends Activity implements PlaybackControlView.VisibilityListener {

    private initExoPlayer() {
        // ...

        addPlaybackControlVisibilityListener(mSimpleExoPlayerView, this);
    }

    @Override
    public void onVisibilityChange(int visibility) {
        // show/hide system ui here
    }

    private static void addPlaybackControlVisibilityListener(SimpleExoPlayerView playerView, PlaybackControlView.VisibilityListener listener) {
        PlaybackControlView playbackControlView = findPlaybackControlView(playerView);
        if (playbackControlView != null)
            playbackControlView.setVisibilityListener(listener);
    }

    private static PlaybackControlView findPlaybackControlView(ViewGroup viewGroup) {
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View child = viewGroup.getChildAt(i);

            if (child instanceof PlaybackControlView)
                return (PlaybackControlView) child;

            if (child instanceof ViewGroup) {
                PlaybackControlView result = findPlaybackControlView((ViewGroup) child);
                if (result != null)
                    return result;
            }
        }

        return null;
    }
}
Tamás Szincsák
  • 1,031
  • 2
  • 12
  • 31
0

With Exoplayer 2.16.1 you can use setControllerVisibilityListener like this:

viewBinding.playerView.setControllerVisibilityListener { visibility ->
    if (visibility == View.VISIBLE) {
        // controller is visible
    } else {
        // controller is not visible
    }
}
Kaaveh Mohamedi
  • 1,399
  • 1
  • 15
  • 36
0

There are two classes we have 1. PlayerView 2. StyledPlayerView. I am answering here for StyledPlayerView since PlayerView is deprecated now.

First create a class which extends StyledPlayerView and also your Class do implement this interface class CustomPlayerView extends StyledPlayerView implements StyledPlayerView.ControllerVisibilityListener So you need to override onVisibilityChanged Method:

@Override
    public void onVisibilityChanged(int visibility) {
      isControllerVisible = visibility == View.VISIBLE;
    }

Now you can call this method on some other class where all your playerView methods present binding.playerView.setControllerVisibilityListener(customPlayerView)

So on Visibility change of your controls you will get callbacks.