Vertical videos in portrait & fullscreen, UI enhancements for tablets and phones, fixes
- vertical videos now work ok in portrait and fullscreen mode at the same time - auto pause on back press is disabled for large tablets - large dragable area for swipe to bottom in fullscreen mode in place of top controls - appbar will be scrolled to top when entering in fullscreen mode
This commit is contained in:
parent
a47e6dd8c5
commit
6d7e37610c
|
@ -870,7 +870,7 @@ public class VideoDetailFragment
|
|||
|
||||
// If we are in fullscreen mode just exit from it via first back press
|
||||
if (player != null && player.isInFullscreen()) {
|
||||
player.onPause();
|
||||
if (!PlayerHelper.isTablet(activity)) player.onPause();
|
||||
restoreDefaultOrientation();
|
||||
setAutoplay(false);
|
||||
return true;
|
||||
|
@ -1699,6 +1699,7 @@ public class VideoDetailFragment
|
|||
if (currentInfo != null && info.getUrl().equals(currentInfo.getUrl())) return;
|
||||
|
||||
currentInfo = info;
|
||||
setInitialData(info.getServiceId(), info.getUrl(),info.getName(), playQueue);
|
||||
setAutoplay(false);
|
||||
prepareAndHandleInfo(info, true);
|
||||
}
|
||||
|
@ -1736,6 +1737,7 @@ public class VideoDetailFragment
|
|||
}
|
||||
|
||||
if (relatedStreamsLayout != null) relatedStreamsLayout.setVisibility(fullscreen ? View.GONE : View.VISIBLE);
|
||||
scrollToTop();
|
||||
|
||||
addVideoPlayerView();
|
||||
}
|
||||
|
@ -1842,12 +1844,10 @@ public class VideoDetailFragment
|
|||
if ((!player.isPlaying() && player.getPlayQueue() != playQueue) || player.getPlayQueue() == null)
|
||||
setAutoplay(true);
|
||||
|
||||
player.checkLandscape();
|
||||
boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(activity);
|
||||
// Let's give a user time to look at video information page if video is not playing
|
||||
if (player.isPlaying()) {
|
||||
player.checkLandscape();
|
||||
} else if (orientationLocked) {
|
||||
player.checkLandscape();
|
||||
if (orientationLocked && !player.isPlaying()) {
|
||||
player.onPlay();
|
||||
player.showControlsThenHide();
|
||||
}
|
||||
|
@ -1927,6 +1927,7 @@ public class VideoDetailFragment
|
|||
case BottomSheetBehavior.STATE_COLLAPSED:
|
||||
// Re-enable clicks
|
||||
setOverlayElementsClickable(true);
|
||||
if (player != null) player.onQueueClosed();
|
||||
break;
|
||||
case BottomSheetBehavior.STATE_DRAGGING:
|
||||
case BottomSheetBehavior.STATE_SETTLING:
|
||||
|
|
|
@ -74,9 +74,11 @@ import org.schabi.newpipe.util.*;
|
|||
import java.util.List;
|
||||
|
||||
import static android.content.Context.WINDOW_SERVICE;
|
||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
import static org.schabi.newpipe.player.MainPlayer.*;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.isTablet;
|
||||
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.animateView;
|
||||
|
@ -137,6 +139,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
|
||||
private boolean audioOnly = false;
|
||||
private boolean isFullscreen = false;
|
||||
private boolean isVerticalVideo = false;
|
||||
boolean shouldUpdateOnProgress;
|
||||
|
||||
private MainPlayer service;
|
||||
|
@ -305,11 +308,13 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
openInBrowser.setVisibility(View.GONE);
|
||||
playerCloseButton.setVisibility(View.GONE);
|
||||
getTopControlsRoot().bringToFront();
|
||||
getTopControlsRoot().setClickable(false);
|
||||
getTopControlsRoot().setFocusable(false);
|
||||
getBottomControlsRoot().bringToFront();
|
||||
onQueueClosed();
|
||||
} else {
|
||||
fullscreenButton.setVisibility(View.GONE);
|
||||
setupScreenRotationButton(service.isLandscape());
|
||||
setupScreenRotationButton();
|
||||
getResizeView().setVisibility(View.VISIBLE);
|
||||
getRootView().findViewById(R.id.metadataView).setVisibility(View.VISIBLE);
|
||||
moreOptionsButton.setVisibility(View.VISIBLE);
|
||||
|
@ -323,6 +328,10 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
defaultPreferences.getBoolean(service.getString(R.string.show_play_with_kodi_key), false) ? View.VISIBLE : View.GONE);
|
||||
openInBrowser.setVisibility(View.VISIBLE);
|
||||
playerCloseButton.setVisibility(isFullscreen ? View.GONE : View.VISIBLE);
|
||||
// Top controls have a large minHeight which is allows to drag the player down in fullscreen mode (just larger area
|
||||
// to make easy to locate by finger)
|
||||
getTopControlsRoot().setClickable(true);
|
||||
getTopControlsRoot().setFocusable(true);
|
||||
}
|
||||
if (!isInFullscreen()) {
|
||||
titleTextView.setVisibility(View.GONE);
|
||||
|
@ -393,7 +402,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
|
||||
settingsContentObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) { setupScreenRotationButton(service.isLandscape()); }
|
||||
public void onChange(boolean selfChange) { setupScreenRotationButton(); }
|
||||
};
|
||||
service.getContentResolver().registerContentObserver(
|
||||
Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), false,
|
||||
|
@ -442,6 +451,14 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
setPlaybackParameters(playbackTempo, playbackPitch, playbackSkipSilence);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
||||
super.onVideoSizeChanged(width, height, unappliedRotationDegrees, pixelWidthHeightRatio);
|
||||
isVerticalVideo = width < height;
|
||||
prepareOrientation();
|
||||
setupScreenRotationButton();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// ExoPlayer Video Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -597,7 +614,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
channelTextView.setVisibility(View.VISIBLE);
|
||||
playerCloseButton.setVisibility(View.GONE);
|
||||
}
|
||||
setupScreenRotationButton(isInFullscreen());
|
||||
setupScreenRotationButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -637,7 +654,8 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
toggleFullscreen();
|
||||
|
||||
} else if (v.getId() == screenRotationButton.getId()) {
|
||||
fragmentListener.onScreenRotationButtonClicked();
|
||||
if (!isVerticalVideo) fragmentListener.onScreenRotationButtonClicked();
|
||||
else toggleFullscreen();
|
||||
|
||||
} else if (v.getId() == playerCloseButton.getId()) {
|
||||
service.sendBroadcast(new Intent(VideoDetailFragment.ACTION_HIDE_MAIN_PLAYER));
|
||||
|
@ -667,6 +685,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
private void onQueueClicked() {
|
||||
queueVisible = true;
|
||||
|
||||
hideSystemUIIfNeeded();
|
||||
buildQueue();
|
||||
updatePlaybackButtons();
|
||||
|
||||
|
@ -677,7 +696,9 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
itemsList.scrollToPosition(playQueue.getIndex());
|
||||
}
|
||||
|
||||
private void onQueueClosed() {
|
||||
public void onQueueClosed() {
|
||||
if (!queueVisible) return;
|
||||
|
||||
animateView(queueLayout, SLIDE_AND_ALPHA, /*visible=*/false,
|
||||
DEFAULT_CONTROLS_DURATION, 0, () -> {
|
||||
// Even when queueLayout is GONE it receives touch events and ruins normal behavior of the app. This line fixes it
|
||||
|
@ -733,11 +754,18 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
builder.create().show();
|
||||
}
|
||||
|
||||
private void setupScreenRotationButton(boolean landscape) {
|
||||
private void setupScreenRotationButton() {
|
||||
boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(service);
|
||||
screenRotationButton.setVisibility(orientationLocked && videoPlayerSelected() ? View.VISIBLE : View.GONE);
|
||||
boolean showButton = (orientationLocked || isVerticalVideo || isTablet(service)) && videoPlayerSelected();
|
||||
screenRotationButton.setVisibility(showButton ? View.VISIBLE : View.GONE);
|
||||
screenRotationButton.setImageDrawable(service.getResources().getDrawable(
|
||||
landscape ? R.drawable.ic_fullscreen_exit_white : R.drawable.ic_fullscreen_white));
|
||||
isInFullscreen() ? R.drawable.ic_fullscreen_exit_white : R.drawable.ic_fullscreen_white));
|
||||
}
|
||||
|
||||
private void prepareOrientation() {
|
||||
boolean orientationLocked = PlayerHelper.globalScreenOrientationLocked(service);
|
||||
if (orientationLocked && isInFullscreen() && service.isLandscape() == isVerticalVideo && fragmentListener != null)
|
||||
fragmentListener.onScreenRotationButtonClicked();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -779,7 +807,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
brightnessProgressBar.setMax(maxGestureLength);
|
||||
|
||||
setInitialGestureValues();
|
||||
queueLayout.getLayoutParams().height = min - queueLayout.getTop();
|
||||
queueLayout.getLayoutParams().height = height - queueLayout.getTop();
|
||||
|
||||
if (popupPlayerSelected()) {
|
||||
float widthDp = Math.abs(r - l) / service.getResources().getDisplayMetrics().density;
|
||||
|
@ -1009,7 +1037,16 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
onRepeatClicked();
|
||||
break;
|
||||
case Intent.ACTION_CONFIGURATION_CHANGED:
|
||||
setControlsSize();
|
||||
// The only situation I need to re-calculate elements sizes is when a user rotates a device from landscape to landscape
|
||||
// because in that case the controls should be aligned to another side of a screen. The problem is when user leaves
|
||||
// the app and returns back (while the app in landscape) Android reports via DisplayMetrics that orientation is
|
||||
// portrait and it gives wrong sizes calculations. Let's skip re-calculation in every case but landscape
|
||||
boolean reportedOrientationIsLandscape = service.isLandscape();
|
||||
boolean actualOrientationIsLandscape = context.getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE;
|
||||
if (reportedOrientationIsLandscape && actualOrientationIsLandscape) setControlsSize();
|
||||
// Close it because when changing orientation from portrait (in fullscreen mode) the size of queue layout can be
|
||||
// larger than the screen size
|
||||
onQueueClosed();
|
||||
break;
|
||||
case Intent.ACTION_SCREEN_ON:
|
||||
shouldUpdateOnProgress = true;
|
||||
|
@ -1201,7 +1238,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
// It doesn't include NavigationBar, notches, etc.
|
||||
display.getSize(size);
|
||||
|
||||
int width = isFullscreen ? size.x : ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
int width = isFullscreen ? (service.isLandscape() ? size.x : size.y) : ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
int gravity = isFullscreen ? (display.getRotation() == Surface.ROTATION_90 ? Gravity.START : Gravity.END) : Gravity.TOP;
|
||||
|
||||
getTopControlsRoot().getLayoutParams().width = width;
|
||||
|
@ -1218,10 +1255,11 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
bottomParams.addRule(gravity == Gravity.END ? RelativeLayout.ALIGN_PARENT_END : RelativeLayout.ALIGN_PARENT_START);
|
||||
getBottomControlsRoot().requestLayout();
|
||||
|
||||
ViewGroup controlsRoot = getRootView().findViewById(R.id.playbackControlRoot);
|
||||
// In tablet navigationBar located at the bottom of the screen. And the only situation when we need to set custom height is
|
||||
// in fullscreen mode in tablet in non-multiWindow mode. Other than that MATCH_PARENT is good
|
||||
controlsRoot.getLayoutParams().height = isFullscreen && !isInMultiWindow() && PlayerHelper.isTablet(service)
|
||||
ViewGroup controlsRoot = getRootView().findViewById(R.id.playbackWindowRoot);
|
||||
// In tablet navigationBar located at the bottom of the screen. And the situations when we need to set custom height is
|
||||
// in fullscreen mode in tablet in non-multiWindow mode or with vertical video. Other than that MATCH_PARENT is good
|
||||
boolean navBarAtTheBottom = PlayerHelper.isTablet(service) || !service.isLandscape();
|
||||
controlsRoot.getLayoutParams().height = isFullscreen && !isInMultiWindow() && navBarAtTheBottom
|
||||
? size.y
|
||||
: ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
controlsRoot.requestLayout();
|
||||
|
@ -1264,9 +1302,12 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
|
||||
public void checkLandscape() {
|
||||
AppCompatActivity parent = getParentActivity();
|
||||
if (parent != null && service.isLandscape() != isInFullscreen()
|
||||
&& getCurrentState() != STATE_COMPLETED && videoPlayerSelected() && !audioOnly)
|
||||
boolean videoInLandscapeButNotInFullscreen = service.isLandscape() && !isInFullscreen() && videoPlayerSelected() && !audioOnly;
|
||||
boolean playingState = getCurrentState() != STATE_COMPLETED && getCurrentState() != STATE_PAUSED;
|
||||
if (parent != null && videoInLandscapeButNotInFullscreen && playingState)
|
||||
toggleFullscreen();
|
||||
|
||||
setControlsSize();
|
||||
}
|
||||
|
||||
private void buildQueue() {
|
||||
|
|
|
@ -160,9 +160,8 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
|
|||
|
||||
isMovingInMain = true;
|
||||
|
||||
boolean acceptAnyArea = isVolumeGestureEnabled != isBrightnessGestureEnabled;
|
||||
boolean acceptVolumeArea = acceptAnyArea || initialEvent.getX() > playerImpl.getRootView().getWidth() / 2;
|
||||
boolean acceptBrightnessArea = acceptAnyArea || !acceptVolumeArea;
|
||||
boolean acceptVolumeArea = initialEvent.getX() > playerImpl.getRootView().getWidth() / 2.0;
|
||||
boolean acceptBrightnessArea = initialEvent.getX() <= playerImpl.getRootView().getWidth() / 2.0;
|
||||
|
||||
if (isVolumeGestureEnabled && acceptVolumeArea) {
|
||||
playerImpl.getVolumeProgressBar().incrementProgressBy((int) distanceY);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
android:id="@+id/surfaceView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
android:layout_centerInParent="true"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/surfaceForeground"
|
||||
|
@ -131,6 +131,12 @@
|
|||
android:background="@drawable/player_top_controls_bg"
|
||||
android:layout_alignParentTop="true" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:background="@drawable/player_controls_bg"
|
||||
android:layout_alignParentBottom="true" />
|
||||
|
||||
<!-- All top controls in this layout -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/playbackWindowRoot"
|
||||
|
@ -144,6 +150,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:orientation="vertical"
|
||||
android:minHeight="80dp"
|
||||
android:gravity="top"
|
||||
android:paddingTop="@dimen/player_main_top_padding"
|
||||
android:paddingStart="@dimen/player_main_controls_padding"
|
||||
|
@ -364,31 +371,26 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/fullScreenButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="@dimen/player_main_buttons_padding"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_fullscreen_white"
|
||||
tools:ignore="ContentDescription,RtlHardcoded"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:background="@drawable/player_controls_bg"
|
||||
android:layout_alignParentBottom="true" />
|
||||
<ImageButton
|
||||
android:id="@+id/fullScreenButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="@dimen/player_main_buttons_padding"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_fullscreen_white"
|
||||
tools:ignore="ContentDescription,RtlHardcoded"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomControls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="40dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
android:id="@+id/surfaceView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
android:layout_centerInParent="true"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/surfaceForeground"
|
||||
|
@ -129,6 +129,12 @@
|
|||
android:background="@drawable/player_top_controls_bg"
|
||||
android:layout_alignParentTop="true" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:background="@drawable/player_controls_bg"
|
||||
android:layout_alignParentBottom="true" />
|
||||
|
||||
<!-- All top controls in this layout -->
|
||||
<RelativeLayout
|
||||
android:id="@+id/playbackWindowRoot"
|
||||
|
@ -142,6 +148,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:orientation="vertical"
|
||||
android:minHeight="80dp"
|
||||
android:gravity="top"
|
||||
android:paddingTop="@dimen/player_main_top_padding"
|
||||
android:paddingStart="@dimen/player_main_controls_padding"
|
||||
|
@ -362,31 +369,26 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/fullScreenButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="@dimen/player_main_buttons_padding"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_fullscreen_white"
|
||||
tools:ignore="ContentDescription,RtlHardcoded"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:background="@drawable/player_controls_bg"
|
||||
android:layout_alignParentBottom="true" />
|
||||
<ImageButton
|
||||
android:id="@+id/fullScreenButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="@dimen/player_main_buttons_padding"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_fullscreen_white"
|
||||
tools:ignore="ContentDescription,RtlHardcoded"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomControls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="40dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
|
|
Loading…
Reference in New Issue