From 71d3227791702901d6c898d4e9a85f0d0eb3cb8c Mon Sep 17 00:00:00 2001 From: TobiGr Date: Sun, 14 Mar 2021 12:50:56 +0100 Subject: [PATCH] Fix bottom controls being out of the screen This was caused by too large end screen thumbnails enlarging the whole palyer. Fixed by scaling the thumbnail. Ensure that the player does not use the whole screen height in detail fragment to keep the additional content like title, comments, etc. available. --- .../org/schabi/newpipe/player/Player.java | 96 +++++++++++++++++-- .../org/schabi/newpipe/util/DeviceUtils.java | 18 ++++ 2 files changed, 108 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 424775928..ab93d8742 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -1129,6 +1129,12 @@ public final class Player implements // Close it because when changing orientation from portrait // (in fullscreen mode) the size of queue layout can be larger than the screen size closeItemsList(); + // When the orientation changed, the screen height might be smaller. + // If the end screen thumbnail is not re-scaled, + // it can be larger than the current screen height + // and thus enlarging the whole player. + // This causes the seekbar to be ouf the visible area. + updateEndScreenThumbnail(); break; case Intent.ACTION_SCREEN_ON: // Interrupt playback only when screen turns on @@ -1187,6 +1193,78 @@ public final class Player implements .loadImage(url, ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS, this); } + /** + * Scale the player audio / end screen thumbnail down if necessary. + *

+ * This is necessary when the thumbnail's height is larger than the device's height + * and thus is enlarging the player's height + * causing the bottom playback controls to be out of the visible screen. + *

+ */ + public void updateEndScreenThumbnail() { + if (currentThumbnail == null) { + return; + } + + final float endScreenHeight = calculateMaxEndScreenThumbnailHeight(); + + final Bitmap endScreenBitmap = Bitmap.createScaledBitmap( + currentThumbnail, + (int) (currentThumbnail.getWidth() + / (currentThumbnail.getHeight() / endScreenHeight)), + (int) endScreenHeight, + true); + + if (DEBUG) { + Log.d(TAG, "Thumbnail - updateEndScreenThumbnail() called with: " + + "currentThumbnail = [" + currentThumbnail + "], " + + currentThumbnail.getWidth() + "x" + currentThumbnail.getHeight() + + ", scaled end screen height = " + endScreenHeight + + ", scaled end screen width = " + endScreenBitmap.getWidth()); + } + + binding.endScreen.setImageBitmap(endScreenBitmap); + } + + /** + * Calculate the maximum allowed height for the {@link R.id.endScreen} + * to prevent it from enlarging the player. + *

+ * The calculating follows these rules: + *

+ * + * @return the maximum height for the end screen thumbnail + */ + private float calculateMaxEndScreenThumbnailHeight() { + // ensure that screenHeight is initialized and thus not 0 + updateScreenSize(); + + if (DeviceUtils.isTv(context) && !isFullscreen) { + final int videoInfoHeight = + DeviceUtils.dpToPx(85, context) + DeviceUtils.spToPx(16, context); + return Math.min(currentThumbnail.getHeight(), screenHeight - videoInfoHeight); + } else if (DeviceUtils.isTablet(context) && service.isLandscape() && !isFullscreen) { + final int videoInfoHeight = + DeviceUtils.dpToPx(85, context) + DeviceUtils.spToPx(15, context); + return Math.min(currentThumbnail.getHeight(), screenHeight - videoInfoHeight); + } else { // fullscreen player: max height is the device height + return Math.min(currentThumbnail.getHeight(), screenHeight); + } + } + @Override public void onLoadingStarted(final String imageUri, final View view) { if (DEBUG) { @@ -1207,23 +1285,29 @@ public final class Player implements @Override public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) { - final float width = Math.min( + // scale down the notification thumbnail for performance + final float notificationThumbnailWidth = Math.min( context.getResources().getDimension(R.dimen.player_notification_thumbnail_width), loadedImage.getWidth()); + currentThumbnail = Bitmap.createScaledBitmap( + loadedImage, + (int) notificationThumbnailWidth, + (int) (loadedImage.getHeight() + / (loadedImage.getWidth() / notificationThumbnailWidth)), + true); if (DEBUG) { Log.d(TAG, "Thumbnail - onLoadingComplete() called with: " + "imageUri = [" + imageUri + "], view = [" + view + "], " + "loadedImage = [" + loadedImage + "], " + loadedImage.getWidth() + "x" + loadedImage.getHeight() - + ", scaled width = " + width); + + ", scaled notification width = " + notificationThumbnailWidth); } - currentThumbnail = Bitmap.createScaledBitmap(loadedImage, - (int) width, - (int) (loadedImage.getHeight() / (loadedImage.getWidth() / width)), true); - binding.endScreen.setImageBitmap(loadedImage); NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false); + + // there is a new thumbnail, thus the end screen thumbnail needs to be changed, too. + updateEndScreenThumbnail(); } @Override 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 1afedcaef..52069fd0e 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -6,8 +6,10 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.BatteryManager; import android.os.Build; +import android.util.TypedValue; import android.view.KeyEvent; +import androidx.annotation.Dimension; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; @@ -70,4 +72,20 @@ public final class DeviceUtils { return false; } } + + public static int dpToPx(@Dimension(unit = Dimension.DP) final int dp, + @NonNull final Context context) { + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp, + context.getResources().getDisplayMetrics()); + } + + public static int spToPx(@Dimension(unit = Dimension.SP) final int sp, + @NonNull final Context context) { + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + sp, + context.getResources().getDisplayMetrics()); + } }