Exoplayer hide PlaybackControlView onClick (not onTouch)

AMD picture AMD · Jan 1, 2017 · Viewed 7.1k times · Source

I am developing a custom UI on top of ExoPlayer, and I noticed that the controls (PlaybackControlView) hide when I touch the screen, not when I click.

I wanted to change to a click and checked how I can change the event listener, but so far could not find an easy solution. I checked the source SimpleExoPlayerView.java and I noticed that it actually is hardcoded:

  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    if (!useController || player == null || ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
      return false;
    }
    if (controller.isVisible()) {
      controller.hide();
    } else {
      maybeShowController(true);
    }
    return true;
  }

So far I could think of two solutions. One is to change the ExoPlayer's source code, but I do not like it since I will have to make modifications every time I update the ExoPlayer.

The second solution I could think of is simply to try to handle it myself, for example, to add my own listeners, and show and hide the controls myself. I have not tried this yet, but it seems possible.

Is there another better solution, like overriding the listeners, etc?

Update: I am using custom UI by inflating exo_playback_control_view.xml

Answer

et_l picture et_l · Jan 1, 2017

By looking at this answer you can see that an OnTouchListener#onTouch is called BEFORE the View#onTouchEvent so you can set an OnTouchListener to the view, consume the MotionEvent and it will not be passed onto the onTouchEvent method.

For example, using this code only "onTouch: LISTENER!!!" is logged when touching the view, and not "onTouchEvent: onTouchEvent!!!":

EDIT - to add your request for a click event handling I added the use of GestureDetector, using this answer - so now upon click "onSingleTapUp: TAP DETECTED" is logged as well.

public class TouchingView extends View {

    private final static String TAG="TouchingView";

    private OnTouchListener touchListener;
    private GestureDetector gestureDetector;

    public TouchingView(Context context) {
        super(context);
        touchListener = new TouchListener();
        gestureDetector = new GestureDetector(getContext(), 
                         (GestureDetector.OnGestureListener) touchListener);
        setOnTouchListener(touchListener);
    }

    public TouchingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        touchListener = new TouchListener();
        gestureDetector = new GestureDetector(getContext(), 
                         (GestureDetector.OnGestureListener) touchListener);
        setOnTouchListener(touchListener);
    }

    public TouchingView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        touchListener = new TouchListener();
        gestureDetector = new GestureDetector(getContext(), 
                         (GestureDetector.OnGestureListener) touchListener);
        setOnTouchListener(touchListener);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(TAG, "onTouchEvent: onTouchEvent!!!"); //not logged
        return super.onTouchEvent(event);
    }

    private class TouchListener extends GestureDetector.SimpleOnGestureListener 
                                implements View.OnTouchListener{

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Log.d(TAG, "onTouch: LISTENER!!!"); //logged upon every touch event. twice upon click (for UP and for DOWN)
            gestureDetector.onTouchEvent(event);
            return true; //preventing the view's onTouchEvent from firing
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) { //you can override onSingleTapConfirmed if you don't want doubleClick to fire it
            Log.d(TAG, "onSingleTapUp: TAP DETECTED"); //logged only upon click
            return true;
        }
    }
}