From cc438fdb7babde33544e2baca2f3b59cb8e10b34 Mon Sep 17 00:00:00 2001 From: Avently <7953703+avently@users.noreply.github.com> Date: Fri, 17 Jan 2020 17:37:53 +0300 Subject: [PATCH] Player's elements positioning is better for tablet and in multiWindow mode - status bar got a fix for situation when a phone vendor did not provide status bar height for landscape orientation - popup will not be init'd twice - also fixed some non-reproduceable bugs --- .../fragments/detail/VideoDetailFragment.java | 50 ++++++++++++------- .../newpipe/player/VideoPlayerImpl.java | 46 +++++++++++++---- .../newpipe/player/helper/PlayerHelper.java | 6 +++ .../activity_main_player.xml | 2 - .../fragment_video_detail.xml | 3 +- .../main/res/layout/activity_main_player.xml | 2 - .../main/res/layout/fragment_video_detail.xml | 3 +- 7 files changed, 74 insertions(+), 38 deletions(-) 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 cfaf0aea4..f4c79e73d 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 @@ -288,8 +288,8 @@ public class VideoDetailFragment } private void stopService() { - getContext().stopService(new Intent(getContext(), MainPlayer.class)); unbind(); + getContext().stopService(new Intent(getContext(), MainPlayer.class)); } @@ -325,7 +325,6 @@ public class VideoDetailFragment PreferenceManager.getDefaultSharedPreferences(activity) .registerOnSharedPreferenceChangeListener(this); - startService(false); setupBroadcastReceiver(); settingsContentObserver = new ContentObserver(new Handler()) { @@ -415,6 +414,7 @@ public class VideoDetailFragment positionSubscriber = null; currentWorker = null; disposables = null; + bottomSheetBehavior.setBottomSheetCallback(null); } @Override @@ -688,6 +688,7 @@ public class VideoDetailFragment detailControlsPopup.setOnTouchListener(getOnControlsTouchListener()); setupBottomPlayer(); + startService(false); } private View.OnTouchListener getOnControlsTouchListener() { @@ -931,8 +932,6 @@ public class VideoDetailFragment boolean streamIsTheSame = this.playQueue != null && this.playQueue.equals(playQueue); // Situation when user switches from players to main player. All needed data is here, we can start watching if (streamIsTheSame) { - //TODO not sure about usefulness of this line in the case when user switches from one player to another - // handleResult(currentInfo); openVideoPlayer(); return; } @@ -1094,17 +1093,17 @@ public class VideoDetailFragment if (playerService == null) { startService(true); return; - } - if (currentInfo == null) return; + } + if (currentInfo == null) return; - PlayQueue queue = setupPlayQueueForIntent(false); + PlayQueue queue = setupPlayQueueForIntent(false); - addVideoPlayerView(); - playerService.getView().setVisibility(View.GONE); + // Video view can have elements visible from popup, We hide it here but once it ready the view will be shown in handleIntent() + playerService.getView().setVisibility(View.GONE); + addVideoPlayerView(); - Intent playerIntent = NavigationHelper.getPlayerIntent( - getContext(), MainPlayer.class, queue, null, true); - activity.startService(playerIntent); + Intent playerIntent = NavigationHelper.getPlayerIntent(getContext(), MainPlayer.class, queue, null, true); + activity.startService(playerIntent); } private void hideMainPlayer() { @@ -1194,7 +1193,7 @@ public class VideoDetailFragment } private void addVideoPlayerView() { - if (player == null) return; + if (player == null || getView() == null) return; FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder); @@ -1213,6 +1212,8 @@ public class VideoDetailFragment } private void makeDefaultHeightForVideoPlaceholder() { + if (getView() == null) return; + FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder); viewHolder.getLayoutParams().height = FrameLayout.LayoutParams.MATCH_PARENT; viewHolder.requestLayout(); @@ -1322,7 +1323,9 @@ public class VideoDetailFragment if (player != null && player.isInFullscreen()) player.toggleFullscreen(); // This will show systemUI and pause the player. // User can tap on Play button and video will be in fullscreen mode again - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + // Note for tablet: trying to avoid orientation changes since it's not easy to physically rotate the tablet every time + if (!PlayerHelper.isTablet(activity)) + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); } /*////////////////////////////////////////////////////////////////////////// @@ -1356,7 +1359,7 @@ public class VideoDetailFragment if(relatedStreamsLayout != null){ if(showRelatedStreams){ - relatedStreamsLayout.setVisibility(View.INVISIBLE); + relatedStreamsLayout.setVisibility(player != null && player.isInFullscreen() ? View.GONE : View.INVISIBLE); }else{ relatedStreamsLayout.setVisibility(View.GONE); } @@ -1383,7 +1386,7 @@ public class VideoDetailFragment getChildFragmentManager().beginTransaction() .replace(R.id.relatedStreamsLayout, RelatedVideosFragment.getInstance(info)) .commitNow(); - relatedStreamsLayout.setVisibility(View.VISIBLE); + relatedStreamsLayout.setVisibility(player != null && player.isInFullscreen() ? View.GONE : View.VISIBLE); } } @@ -1722,6 +1725,13 @@ public class VideoDetailFragment @Override public void onScreenRotationButtonClicked() { + // In tablet user experience will be better if screen will not be rotated from landscape to portrait every time + // Just turn on fullscreen mode in landscape orientation + if (isLandscape() && PlayerHelper.isTablet(activity)) { + player.toggleFullscreen(); + return; + } + int newOrientation = isLandscape() ? ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED : ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; @@ -1866,10 +1876,12 @@ public class VideoDetailFragment final int peekHeight = getResources().getDimensionPixelSize(R.dimen.mini_player_height); if (bottomSheetState != BottomSheetBehavior.STATE_HIDDEN) { bottomSheetBehavior.setPeekHeight(peekHeight); - if (bottomSheetState == BottomSheetBehavior.STATE_COLLAPSED) - setOverlayLook(appBarLayout, behavior, 1 - MAX_OVERLAY_ALPHA); - else if (bottomSheetState == BottomSheetBehavior.STATE_EXPANDED) + if (bottomSheetState == BottomSheetBehavior.STATE_COLLAPSED) { + overlay.setAlpha(MAX_OVERLAY_ALPHA); + } else if (bottomSheetState == BottomSheetBehavior.STATE_EXPANDED) { + overlay.setAlpha(0); setOverlayElementsClickable(false); + } } bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { 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 66407936c..4c2740edc 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java @@ -1155,18 +1155,20 @@ 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 spaceBeforeTopControls = getRootView().findViewById(R.id.spaceBeforeControls).getWidth(); + int widthForTopControls = isFullscreen ? size.x - spaceBeforeTopControls : ViewGroup.LayoutParams.MATCH_PARENT; + int widthForBottomControls = isFullscreen ? size.x : ViewGroup.LayoutParams.MATCH_PARENT; int gravity = isFullscreen ? (display.getRotation() == Surface.ROTATION_90 ? Gravity.START : Gravity.END) : Gravity.TOP; - primaryControls.getLayoutParams().width = width; + primaryControls.getLayoutParams().width = widthForTopControls; ((LinearLayout.LayoutParams) primaryControls.getLayoutParams()).gravity = gravity; primaryControls.requestLayout(); - secondaryControls.getLayoutParams().width = width; + secondaryControls.getLayoutParams().width = widthForTopControls; ((LinearLayout.LayoutParams) secondaryControls.getLayoutParams()).gravity = gravity; secondaryControls.requestLayout(); - getBottomControlsRoot().getLayoutParams().width = width; + getBottomControlsRoot().getLayoutParams().width = widthForBottomControls; RelativeLayout.LayoutParams bottomParams = ((RelativeLayout.LayoutParams) getBottomControlsRoot().getLayoutParams()); bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_START); bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_END); @@ -1174,15 +1176,33 @@ public class VideoPlayerImpl extends VideoPlayer getBottomControlsRoot().requestLayout(); ViewGroup controlsRoot = getRootView().findViewById(R.id.playbackControlRoot); - controlsRoot.getLayoutParams().height = isFullscreen ? size.y : ViewGroup.LayoutParams.MATCH_PARENT; + // 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) + ? size.y + : ViewGroup.LayoutParams.MATCH_PARENT; controlsRoot.requestLayout(); + int topPadding = isFullscreen && !isInMultiWindow() ? getStatusBarHeight() : 0; + getRootView().findViewById(R.id.playbackWindowRoot).setPadding(0, topPadding, 0, 0); + getRootView().findViewById(R.id.playbackWindowRoot).requestLayout(); + } + + private int getStatusBarHeight() { int statusBarHeight = 0; int resourceId = service.getResources().getIdentifier("status_bar_height_landscape", "dimen", "android"); if (resourceId > 0) statusBarHeight = service.getResources().getDimensionPixelSize(resourceId); + if (statusBarHeight == 0) { + // Some devices provide wrong value for status bar height in landscape mode, this is workaround + DisplayMetrics metrics = getRootView().getResources().getDisplayMetrics(); + statusBarHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, metrics); + } + return statusBarHeight; + } - getRootView().findViewById(R.id.playbackWindowRoot).setPadding(0, isFullscreen ? statusBarHeight : 0, 0, 0); - getRootView().findViewById(R.id.playbackWindowRoot).requestLayout(); + private boolean isInMultiWindow() { + AppCompatActivity parent = getParentActivity(); + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && parent != null && parent.isInMultiWindowMode(); } private void updatePlaybackButtons() { @@ -1287,6 +1307,9 @@ public class VideoPlayerImpl extends VideoPlayer private void initPopup() { if (DEBUG) Log.d(TAG, "initPopup() called"); + // Popup is already added to windowManager + if (getRootView().getLayoutParams() instanceof WindowManager.LayoutParams) return; + updateScreenSize(); final boolean popupRememberSizeAndPos = PlayerHelper.isRememberingPopupDimensions(service); @@ -1326,6 +1349,10 @@ public class VideoPlayerImpl extends VideoPlayer @SuppressLint("RtlHardcoded") private void initPopupCloseOverlay() { if (DEBUG) Log.d(TAG, "initPopupCloseOverlay() called"); + + // closeOverlayView is already added to windowManager + if (closeOverlayView != null) return; + closeOverlayView = View.inflate(service, R.layout.player_popup_close_overlay, null); closeOverlayButton = closeOverlayView.findViewById(R.id.closeButton); @@ -1493,6 +1520,7 @@ public class VideoPlayerImpl extends VideoPlayer private void end() { windowManager.removeView(closeOverlayView); + closeOverlayView = null; service.onDestroy(); } @@ -1653,10 +1681,6 @@ public class VideoPlayerImpl extends VideoPlayer return closeOverlayButton; } - public View getCloseOverlayView() { - return closeOverlayView; - } - public View getClosingOverlayView() { return closingOverlayView; } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index cfce6e678..ae1cac382 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -2,6 +2,7 @@ package org.schabi.newpipe.player.helper; import android.content.Context; import android.content.SharedPreferences; +import android.content.res.Configuration; import android.os.Build; import android.preference.PreferenceManager; import android.provider.Settings; @@ -329,6 +330,11 @@ public class PlayerHelper { context.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 1); } + public static boolean isTablet(@NonNull final Context context) { + return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) + >= Configuration.SCREENLAYOUT_SIZE_LARGE; + } + //////////////////////////////////////////////////////////////////////////// // Private helpers //////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/res/layout-large-land/activity_main_player.xml b/app/src/main/res/layout-large-land/activity_main_player.xml index 16a52cdb6..73a1113c6 100644 --- a/app/src/main/res/layout-large-land/activity_main_player.xml +++ b/app/src/main/res/layout-large-land/activity_main_player.xml @@ -161,7 +161,6 @@ android:orientation="vertical" android:gravity="top" android:paddingTop="4dp" - android:paddingEnd="6dp" android:layout_toEndOf="@id/spaceBeforeControls" android:baselineAligned="false"> @@ -172,7 +171,6 @@ android:baselineAligned="false" android:gravity="top" android:paddingBottom="7dp" - android:paddingLeft="2dp" tools:ignore="RtlHardcoded"> diff --git a/app/src/main/res/layout/activity_main_player.xml b/app/src/main/res/layout/activity_main_player.xml index 1a0fb292f..cf44d6bcb 100644 --- a/app/src/main/res/layout/activity_main_player.xml +++ b/app/src/main/res/layout/activity_main_player.xml @@ -159,7 +159,6 @@ android:orientation="vertical" android:gravity="top" android:paddingTop="4dp" - android:paddingEnd="6dp" android:layout_toEndOf="@id/spaceBeforeControls" android:baselineAligned="false"> @@ -170,7 +169,6 @@ android:baselineAligned="false" android:gravity="top" android:paddingBottom="7dp" - android:paddingLeft="2dp" tools:ignore="RtlHardcoded">