diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 42a5cbf02..b731d0270 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -1977,6 +1977,11 @@ public class VideoDetailFragment return; } + // Prevent jumping of the player on devices with cutout + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + activity.getWindow().getAttributes().layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; + } activity.getWindow().getDecorView().setSystemUiVisibility(0); activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); } @@ -1990,6 +1995,11 @@ public class VideoDetailFragment return; } + // Prevent jumping of the player on devices with cutout + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + activity.getWindow().getAttributes().layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; + } final int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java index 05680baeb..a5758301c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java @@ -915,8 +915,8 @@ public class VideoPlayerImpl extends VideoPlayer // show kodi button if it supports the current service and it is enabled in settings final boolean showKodiButton = playQueue != null && playQueue.getItem() != null && KoreUtil.isServiceSupportedByKore(playQueue.getItem().getServiceId()) - && PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(context.getString(R.string.show_play_with_kodi_key), false); + && PreferenceManager.getDefaultSharedPreferences(context) + .getBoolean(context.getString(R.string.show_play_with_kodi_key), false); playWithKodi.setVisibility(videoPlayerSelected() && kodiEnabled && showKodiButton ? View.VISIBLE : View.GONE); } @@ -1499,9 +1499,10 @@ public class VideoPlayerImpl extends VideoPlayer // It doesn't include NavigationBar, notches, etc. display.getSize(size); + final boolean isLandscape = service.isLandscape(); final int width = isFullscreen - ? (service.isLandscape() - ? size.x : size.y) : ViewGroup.LayoutParams.MATCH_PARENT; + ? (isLandscape ? size.x : size.y) + : ViewGroup.LayoutParams.MATCH_PARENT; final int gravity = isFullscreen ? (display.getRotation() == Surface.ROTATION_90 ? Gravity.START : Gravity.END) @@ -1532,14 +1533,16 @@ public class VideoPlayerImpl extends VideoPlayer // 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 - final boolean navBarAtTheBottom = DeviceUtils.isTablet(service) || !service.isLandscape(); + final boolean navBarAtTheBottom = DeviceUtils.isTablet(service) || !isLandscape; controlsRoot.getLayoutParams().height = isFullscreen && !isInMultiWindow() && navBarAtTheBottom ? size.y : ViewGroup.LayoutParams.MATCH_PARENT; controlsRoot.requestLayout(); - final int topPadding = isFullscreen && !isInMultiWindow() ? getStatusBarHeight() : 0; - getRootView().findViewById(R.id.playbackWindowRoot).setPadding(0, topPadding, 0, 0); - getRootView().findViewById(R.id.playbackWindowRoot).requestLayout(); + final DisplayMetrics metrics = getRootView().getResources().getDisplayMetrics(); + int topPadding = isFullscreen && !isInMultiWindow() ? getStatusBarHeight() : 0; + topPadding = !isLandscape && DeviceUtils.hasCutout(topPadding, metrics) ? 0 : topPadding; + getRootView().findViewById(R.id.playbackWindowRoot).setTranslationY(topPadding); + getBottomControlsRoot().setTranslationY(-topPadding); } /** @@ -1548,8 +1551,12 @@ public class VideoPlayerImpl extends VideoPlayer */ private int getStatusBarHeight() { int statusBarHeight = 0; - final int resourceId = service.getResources().getIdentifier( - "status_bar_height_landscape", "dimen", "android"); + final int resourceId = service.isLandscape() + ? service.getResources().getIdentifier( + "status_bar_height_landscape", "dimen", "android") + : service.getResources().getIdentifier( + "status_bar_height", "dimen", "android"); + if (resourceId > 0) { statusBarHeight = service.getResources().getDimensionPixelSize(resourceId); } @@ -2081,7 +2088,7 @@ public class VideoPlayerImpl extends VideoPlayer * This will be called when a user goes to another app/activity, turns off a screen. * We don't want to interrupt playback and don't want to see notification so * next lines of code will enable audio-only playback only if needed - * */ + */ private void onFragmentStopped() { if (videoPlayerSelected() && (isPlaying() || isLoading())) { if (backgroundPlaybackEnabled()) { diff --git a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java index d852c2296..7592d2f35 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -6,6 +6,8 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.BatteryManager; import android.os.Build; +import android.util.DisplayMetrics; +import android.util.TypedValue; import android.view.KeyEvent; import androidx.annotation.NonNull; @@ -72,4 +74,17 @@ public final class DeviceUtils { return false; } } + + /* + * Compares current status bar height with default status bar height in Android and decides, + * does the device has cutout or not + * */ + public static boolean hasCutout(final float statusBarHeight, final DisplayMetrics metrics) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + final float defaultStatusBarHeight = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, 25, metrics); + return statusBarHeight > defaultStatusBarHeight; + } + return false; + } }