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
This commit is contained in:
Avently 2020-01-17 17:37:53 +03:00
parent 92ff98d99a
commit cc438fdb7b
7 changed files with 74 additions and 38 deletions

View file

@ -288,8 +288,8 @@ public class VideoDetailFragment
} }
private void stopService() { private void stopService() {
getContext().stopService(new Intent(getContext(), MainPlayer.class));
unbind(); unbind();
getContext().stopService(new Intent(getContext(), MainPlayer.class));
} }
@ -325,7 +325,6 @@ public class VideoDetailFragment
PreferenceManager.getDefaultSharedPreferences(activity) PreferenceManager.getDefaultSharedPreferences(activity)
.registerOnSharedPreferenceChangeListener(this); .registerOnSharedPreferenceChangeListener(this);
startService(false);
setupBroadcastReceiver(); setupBroadcastReceiver();
settingsContentObserver = new ContentObserver(new Handler()) { settingsContentObserver = new ContentObserver(new Handler()) {
@ -415,6 +414,7 @@ public class VideoDetailFragment
positionSubscriber = null; positionSubscriber = null;
currentWorker = null; currentWorker = null;
disposables = null; disposables = null;
bottomSheetBehavior.setBottomSheetCallback(null);
} }
@Override @Override
@ -688,6 +688,7 @@ public class VideoDetailFragment
detailControlsPopup.setOnTouchListener(getOnControlsTouchListener()); detailControlsPopup.setOnTouchListener(getOnControlsTouchListener());
setupBottomPlayer(); setupBottomPlayer();
startService(false);
} }
private View.OnTouchListener getOnControlsTouchListener() { private View.OnTouchListener getOnControlsTouchListener() {
@ -931,8 +932,6 @@ public class VideoDetailFragment
boolean streamIsTheSame = this.playQueue != null && this.playQueue.equals(playQueue); 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 // Situation when user switches from players to main player. All needed data is here, we can start watching
if (streamIsTheSame) { if (streamIsTheSame) {
//TODO not sure about usefulness of this line in the case when user switches from one player to another
// handleResult(currentInfo);
openVideoPlayer(); openVideoPlayer();
return; return;
} }
@ -1099,11 +1098,11 @@ public class VideoDetailFragment
PlayQueue queue = setupPlayQueueForIntent(false); PlayQueue queue = setupPlayQueueForIntent(false);
addVideoPlayerView(); // 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); playerService.getView().setVisibility(View.GONE);
addVideoPlayerView();
Intent playerIntent = NavigationHelper.getPlayerIntent( Intent playerIntent = NavigationHelper.getPlayerIntent(getContext(), MainPlayer.class, queue, null, true);
getContext(), MainPlayer.class, queue, null, true);
activity.startService(playerIntent); activity.startService(playerIntent);
} }
@ -1194,7 +1193,7 @@ public class VideoDetailFragment
} }
private void addVideoPlayerView() { private void addVideoPlayerView() {
if (player == null) return; if (player == null || getView() == null) return;
FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder); FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder);
@ -1213,6 +1212,8 @@ public class VideoDetailFragment
} }
private void makeDefaultHeightForVideoPlaceholder() { private void makeDefaultHeightForVideoPlaceholder() {
if (getView() == null) return;
FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder); FrameLayout viewHolder = getView().findViewById(R.id.player_placeholder);
viewHolder.getLayoutParams().height = FrameLayout.LayoutParams.MATCH_PARENT; viewHolder.getLayoutParams().height = FrameLayout.LayoutParams.MATCH_PARENT;
viewHolder.requestLayout(); viewHolder.requestLayout();
@ -1322,6 +1323,8 @@ public class VideoDetailFragment
if (player != null && player.isInFullscreen()) player.toggleFullscreen(); if (player != null && player.isInFullscreen()) player.toggleFullscreen();
// This will show systemUI and pause the player. // This will show systemUI and pause the player.
// User can tap on Play button and video will be in fullscreen mode again // User can tap on Play button and video will be in fullscreen mode again
// 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); activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
} }
@ -1356,7 +1359,7 @@ public class VideoDetailFragment
if(relatedStreamsLayout != null){ if(relatedStreamsLayout != null){
if(showRelatedStreams){ if(showRelatedStreams){
relatedStreamsLayout.setVisibility(View.INVISIBLE); relatedStreamsLayout.setVisibility(player != null && player.isInFullscreen() ? View.GONE : View.INVISIBLE);
}else{ }else{
relatedStreamsLayout.setVisibility(View.GONE); relatedStreamsLayout.setVisibility(View.GONE);
} }
@ -1383,7 +1386,7 @@ public class VideoDetailFragment
getChildFragmentManager().beginTransaction() getChildFragmentManager().beginTransaction()
.replace(R.id.relatedStreamsLayout, RelatedVideosFragment.getInstance(info)) .replace(R.id.relatedStreamsLayout, RelatedVideosFragment.getInstance(info))
.commitNow(); .commitNow();
relatedStreamsLayout.setVisibility(View.VISIBLE); relatedStreamsLayout.setVisibility(player != null && player.isInFullscreen() ? View.GONE : View.VISIBLE);
} }
} }
@ -1722,6 +1725,13 @@ public class VideoDetailFragment
@Override @Override
public void onScreenRotationButtonClicked() { 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() ? int newOrientation = isLandscape() ?
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
: ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; : ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
@ -1866,11 +1876,13 @@ public class VideoDetailFragment
final int peekHeight = getResources().getDimensionPixelSize(R.dimen.mini_player_height); final int peekHeight = getResources().getDimensionPixelSize(R.dimen.mini_player_height);
if (bottomSheetState != BottomSheetBehavior.STATE_HIDDEN) { if (bottomSheetState != BottomSheetBehavior.STATE_HIDDEN) {
bottomSheetBehavior.setPeekHeight(peekHeight); bottomSheetBehavior.setPeekHeight(peekHeight);
if (bottomSheetState == BottomSheetBehavior.STATE_COLLAPSED) if (bottomSheetState == BottomSheetBehavior.STATE_COLLAPSED) {
setOverlayLook(appBarLayout, behavior, 1 - MAX_OVERLAY_ALPHA); overlay.setAlpha(MAX_OVERLAY_ALPHA);
else if (bottomSheetState == BottomSheetBehavior.STATE_EXPANDED) } else if (bottomSheetState == BottomSheetBehavior.STATE_EXPANDED) {
overlay.setAlpha(0);
setOverlayElementsClickable(false); setOverlayElementsClickable(false);
} }
}
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override public void onStateChanged(@NonNull View bottomSheet, int newState) { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) {

View file

@ -1155,18 +1155,20 @@ public class VideoPlayerImpl extends VideoPlayer
// It doesn't include NavigationBar, notches, etc. // It doesn't include NavigationBar, notches, etc.
display.getSize(size); 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; 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; ((LinearLayout.LayoutParams) primaryControls.getLayoutParams()).gravity = gravity;
primaryControls.requestLayout(); primaryControls.requestLayout();
secondaryControls.getLayoutParams().width = width; secondaryControls.getLayoutParams().width = widthForTopControls;
((LinearLayout.LayoutParams) secondaryControls.getLayoutParams()).gravity = gravity; ((LinearLayout.LayoutParams) secondaryControls.getLayoutParams()).gravity = gravity;
secondaryControls.requestLayout(); secondaryControls.requestLayout();
getBottomControlsRoot().getLayoutParams().width = width; getBottomControlsRoot().getLayoutParams().width = widthForBottomControls;
RelativeLayout.LayoutParams bottomParams = ((RelativeLayout.LayoutParams) getBottomControlsRoot().getLayoutParams()); RelativeLayout.LayoutParams bottomParams = ((RelativeLayout.LayoutParams) getBottomControlsRoot().getLayoutParams());
bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_START); bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_START);
bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_END); bottomParams.removeRule(RelativeLayout.ALIGN_PARENT_END);
@ -1174,15 +1176,33 @@ public class VideoPlayerImpl extends VideoPlayer
getBottomControlsRoot().requestLayout(); getBottomControlsRoot().requestLayout();
ViewGroup controlsRoot = getRootView().findViewById(R.id.playbackControlRoot); 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(); 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 statusBarHeight = 0;
int resourceId = service.getResources().getIdentifier("status_bar_height_landscape", "dimen", "android"); int resourceId = service.getResources().getIdentifier("status_bar_height_landscape", "dimen", "android");
if (resourceId > 0) statusBarHeight = service.getResources().getDimensionPixelSize(resourceId); 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); private boolean isInMultiWindow() {
getRootView().findViewById(R.id.playbackWindowRoot).requestLayout(); AppCompatActivity parent = getParentActivity();
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && parent != null && parent.isInMultiWindowMode();
} }
private void updatePlaybackButtons() { private void updatePlaybackButtons() {
@ -1287,6 +1307,9 @@ public class VideoPlayerImpl extends VideoPlayer
private void initPopup() { private void initPopup() {
if (DEBUG) Log.d(TAG, "initPopup() called"); if (DEBUG) Log.d(TAG, "initPopup() called");
// Popup is already added to windowManager
if (getRootView().getLayoutParams() instanceof WindowManager.LayoutParams) return;
updateScreenSize(); updateScreenSize();
final boolean popupRememberSizeAndPos = PlayerHelper.isRememberingPopupDimensions(service); final boolean popupRememberSizeAndPos = PlayerHelper.isRememberingPopupDimensions(service);
@ -1326,6 +1349,10 @@ public class VideoPlayerImpl extends VideoPlayer
@SuppressLint("RtlHardcoded") @SuppressLint("RtlHardcoded")
private void initPopupCloseOverlay() { private void initPopupCloseOverlay() {
if (DEBUG) Log.d(TAG, "initPopupCloseOverlay() called"); 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); closeOverlayView = View.inflate(service, R.layout.player_popup_close_overlay, null);
closeOverlayButton = closeOverlayView.findViewById(R.id.closeButton); closeOverlayButton = closeOverlayView.findViewById(R.id.closeButton);
@ -1493,6 +1520,7 @@ public class VideoPlayerImpl extends VideoPlayer
private void end() { private void end() {
windowManager.removeView(closeOverlayView); windowManager.removeView(closeOverlayView);
closeOverlayView = null;
service.onDestroy(); service.onDestroy();
} }
@ -1653,10 +1681,6 @@ public class VideoPlayerImpl extends VideoPlayer
return closeOverlayButton; return closeOverlayButton;
} }
public View getCloseOverlayView() {
return closeOverlayView;
}
public View getClosingOverlayView() { public View getClosingOverlayView() {
return closingOverlayView; return closingOverlayView;
} }

View file

@ -2,6 +2,7 @@ package org.schabi.newpipe.player.helper;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build; import android.os.Build;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.provider.Settings; import android.provider.Settings;
@ -329,6 +330,11 @@ public class PlayerHelper {
context.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0) == 1); 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 // Private helpers
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////

View file

@ -161,7 +161,6 @@
android:orientation="vertical" android:orientation="vertical"
android:gravity="top" android:gravity="top"
android:paddingTop="4dp" android:paddingTop="4dp"
android:paddingEnd="6dp"
android:layout_toEndOf="@id/spaceBeforeControls" android:layout_toEndOf="@id/spaceBeforeControls"
android:baselineAligned="false"> android:baselineAligned="false">
@ -172,7 +171,6 @@
android:baselineAligned="false" android:baselineAligned="false"
android:gravity="top" android:gravity="top"
android:paddingBottom="7dp" android:paddingBottom="7dp"
android:paddingLeft="2dp"
tools:ignore="RtlHardcoded"> tools:ignore="RtlHardcoded">
<ImageButton <ImageButton

View file

@ -557,8 +557,7 @@
android:id="@+id/overlay_layout" android:id="@+id/overlay_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:alpha="0" android:alpha="0.9"
tools:alpha="1"
android:paddingLeft="@dimen/video_item_search_padding" android:paddingLeft="@dimen/video_item_search_padding"
android:paddingRight="@dimen/video_item_search_padding" android:paddingRight="@dimen/video_item_search_padding"
android:background="?attr/windowBackground" > android:background="?attr/windowBackground" >

View file

@ -159,7 +159,6 @@
android:orientation="vertical" android:orientation="vertical"
android:gravity="top" android:gravity="top"
android:paddingTop="4dp" android:paddingTop="4dp"
android:paddingEnd="6dp"
android:layout_toEndOf="@id/spaceBeforeControls" android:layout_toEndOf="@id/spaceBeforeControls"
android:baselineAligned="false"> android:baselineAligned="false">
@ -170,7 +169,6 @@
android:baselineAligned="false" android:baselineAligned="false"
android:gravity="top" android:gravity="top"
android:paddingBottom="7dp" android:paddingBottom="7dp"
android:paddingLeft="2dp"
tools:ignore="RtlHardcoded"> tools:ignore="RtlHardcoded">
<ImageButton <ImageButton

View file

@ -547,8 +547,7 @@
android:id="@+id/overlay_layout" android:id="@+id/overlay_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:alpha="0" android:alpha="0.9"
tools:alpha="1"
android:background="?attr/windowBackground" > android:background="?attr/windowBackground" >
<ImageButton <ImageButton