Improve usability of MainVideoActivity with directional navigation

* Hide player controls when back is pressed (only on TV devices)
* Do not hide control after click unless in touch mode
* Show player controls on dpad usage
* Notably increase control hide timeout when not in touch mode
This commit is contained in:
Alexander 2019-09-20 16:36:57 +07:00 committed by Alexander--
parent 644ad110c0
commit d29e0aa1a7
2 changed files with 66 additions and 2 deletions

View File

@ -1,5 +1,6 @@
/* /*
* Copyright 2017 Mauricio Colli <mauriciocolli@outlook.com> * Copyright 2017 Mauricio Colli <mauriciocolli@outlook.com>
* Copyright 2019 Eltex ltd <eltex@eltex-co.ru>
* MainVideoPlayer.java is part of NewPipe * MainVideoPlayer.java is part of NewPipe
* *
* License: GPL-3.0+ * License: GPL-3.0+
@ -45,6 +46,7 @@ import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
@ -75,6 +77,7 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
import org.schabi.newpipe.player.resolver.MediaSourceTag; import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver; import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.FireTvUtils;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.PermissionHelper;
@ -89,6 +92,7 @@ import java.util.UUID;
import static org.schabi.newpipe.player.BasePlayer.STATE_PLAYING; import static org.schabi.newpipe.player.BasePlayer.STATE_PLAYING;
import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_DURATION; import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_DURATION;
import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_HIDE_TIME; import static org.schabi.newpipe.player.VideoPlayer.DEFAULT_CONTROLS_HIDE_TIME;
import static org.schabi.newpipe.player.VideoPlayer.DPAD_CONTROLS_HIDE_TIME;
import static org.schabi.newpipe.util.AnimationUtils.Type.SCALE_AND_ALPHA; import static org.schabi.newpipe.util.AnimationUtils.Type.SCALE_AND_ALPHA;
import static org.schabi.newpipe.util.AnimationUtils.Type.SLIDE_AND_ALPHA; import static org.schabi.newpipe.util.AnimationUtils.Type.SLIDE_AND_ALPHA;
import static org.schabi.newpipe.util.AnimationUtils.animateRotation; import static org.schabi.newpipe.util.AnimationUtils.animateRotation;
@ -187,6 +191,40 @@ public final class MainVideoPlayer extends AppCompatActivity
} }
} }
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (event.getKeyCode()) {
default:
break;
case KeyEvent.KEYCODE_BACK:
if (FireTvUtils.isFireTv() && playerImpl.isControlsVisible()) {
playerImpl.hideControls(0, 0);
hideSystemUi();
return true;
}
break;
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_CENTER:
if (playerImpl.getCurrentState() == BasePlayer.STATE_BLOCKED) {
return true;
}
if (!playerImpl.isControlsVisible()) {
playerImpl.showControlsThenHide();
showSystemUi();
return true;
} else {
playerImpl.hideControls(DEFAULT_CONTROLS_DURATION, DPAD_CONTROLS_HIDE_TIME);
}
break;
}
return super.onKeyDown(keyCode, event);
}
@Override @Override
protected void onResume() { protected void onResume() {
if (DEBUG) Log.d(TAG, "onResume() called"); if (DEBUG) Log.d(TAG, "onResume() called");
@ -692,7 +730,7 @@ public final class MainVideoPlayer extends AppCompatActivity
getControlsVisibilityHandler().removeCallbacksAndMessages(null); getControlsVisibilityHandler().removeCallbacksAndMessages(null);
animateView(getControlsRoot(), true, DEFAULT_CONTROLS_DURATION, 0, () -> { animateView(getControlsRoot(), true, DEFAULT_CONTROLS_DURATION, 0, () -> {
if (getCurrentState() == STATE_PLAYING && !isSomePopupMenuVisible()) { if (getCurrentState() == STATE_PLAYING && !isSomePopupMenuVisible()) {
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); safeHideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
} }
}); });
} }
@ -898,6 +936,18 @@ public final class MainVideoPlayer extends AppCompatActivity
super.showControls(duration); super.showControls(duration);
} }
@Override
public void safeHideControls(long duration, long delay) {
if (DEBUG) Log.d(TAG, "safeHideControls() called with: delay = [" + delay + "]");
View controlsRoot = getControlsRoot();
if (controlsRoot.isInTouchMode()) {
getControlsVisibilityHandler().removeCallbacksAndMessages(null);
getControlsVisibilityHandler().postDelayed(
() -> animateView(controlsRoot, false, duration, 0, MainVideoPlayer.this::hideSystemUi), delay);
}
}
@Override @Override
public void hideControls(final long duration, long delay) { public void hideControls(final long duration, long delay) {
if (DEBUG) Log.d(TAG, "hideControls() called with: delay = [" + delay + "]"); if (DEBUG) Log.d(TAG, "hideControls() called with: delay = [" + delay + "]");
@ -1058,6 +1108,7 @@ public final class MainVideoPlayer extends AppCompatActivity
playerImpl.showControlsThenHide(); playerImpl.showControlsThenHide();
showSystemUi(); showSystemUi();
} }
return true; return true;
} }

View File

@ -97,6 +97,7 @@ public abstract class VideoPlayer extends BasePlayer
protected static final int RENDERER_UNAVAILABLE = -1; protected static final int RENDERER_UNAVAILABLE = -1;
public static final int DEFAULT_CONTROLS_DURATION = 300; // 300 millis public static final int DEFAULT_CONTROLS_DURATION = 300; // 300 millis
public static final int DEFAULT_CONTROLS_HIDE_TIME = 2000; // 2 Seconds public static final int DEFAULT_CONTROLS_HIDE_TIME = 2000; // 2 Seconds
public static final int DPAD_CONTROLS_HIDE_TIME = 7000; // 7 Seconds
private List<VideoStream> availableStreams; private List<VideoStream> availableStreams;
private int selectedStreamIndex; private int selectedStreamIndex;
@ -825,8 +826,11 @@ public abstract class VideoPlayer extends BasePlayer
public void showControlsThenHide() { public void showControlsThenHide() {
if (DEBUG) Log.d(TAG, "showControlsThenHide() called"); if (DEBUG) Log.d(TAG, "showControlsThenHide() called");
final int hideTime = controlsRoot.isInTouchMode() ? DEFAULT_CONTROLS_HIDE_TIME : DPAD_CONTROLS_HIDE_TIME;
animateView(controlsRoot, true, DEFAULT_CONTROLS_DURATION, 0, animateView(controlsRoot, true, DEFAULT_CONTROLS_DURATION, 0,
() -> hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME)); () -> hideControls(DEFAULT_CONTROLS_DURATION, hideTime));
} }
public void showControls(long duration) { public void showControls(long duration) {
@ -835,6 +839,15 @@ public abstract class VideoPlayer extends BasePlayer
animateView(controlsRoot, true, duration); animateView(controlsRoot, true, duration);
} }
public void safeHideControls(final long duration, long delay) {
if (DEBUG) Log.d(TAG, "safeHideControls() called with: delay = [" + delay + "]");
if (rootView.isInTouchMode()) {
controlsVisibilityHandler.removeCallbacksAndMessages(null);
controlsVisibilityHandler.postDelayed(
() -> animateView(controlsRoot, false, duration), delay);
}
}
public void hideControls(final long duration, long delay) { public void hideControls(final long duration, long delay) {
if (DEBUG) Log.d(TAG, "hideControls() called with: delay = [" + delay + "]"); if (DEBUG) Log.d(TAG, "hideControls() called with: delay = [" + delay + "]");
controlsVisibilityHandler.removeCallbacksAndMessages(null); controlsVisibilityHandler.removeCallbacksAndMessages(null);