Second block of fixes for review
- hide/show controls with respect of SystemUI. In fullscreen mode controls will stay away from NavigationBar - notification from running service will be hidden if a user disabled background playback - fixed incorrect handling of a system method in API 19 - better MultiWindow support
This commit is contained in:
parent
bc2dc8d933
commit
4519dd010d
9 changed files with 87 additions and 50 deletions
|
@ -1244,7 +1244,7 @@ public class VideoDetailFragment
|
|||
|
||||
int height;
|
||||
if (player != null && player.isInFullscreen())
|
||||
height = activity.getWindow().getDecorView().getHeight();
|
||||
height = isInMultiWindow() ? getView().getHeight() : activity.getWindow().getDecorView().getHeight();
|
||||
else
|
||||
height = isPortrait
|
||||
? (int) (metrics.widthPixels / (16.0f / 9.0f))
|
||||
|
@ -1669,8 +1669,7 @@ public class VideoDetailFragment
|
|||
player.useVideoSource(false);
|
||||
else if (player.minimizeOnPopupEnabled())
|
||||
NavigationHelper.playOnPopupPlayer(activity, playQueue, true);
|
||||
else
|
||||
player.getPlayer().setPlayWhenReady(false);
|
||||
else player.onPause();
|
||||
}
|
||||
else player.useVideoSource(true);
|
||||
}
|
||||
|
@ -1751,23 +1750,18 @@ public class VideoDetailFragment
|
|||
|
||||
getActivity().getWindow().getDecorView().setSystemUiVisibility(0);
|
||||
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
|
||||
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
}
|
||||
|
||||
private void hideSystemUi() {
|
||||
if (DEBUG) Log.d(TAG, "hideSystemUi() called");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
visibility |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||
}
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||
activity.getWindow().getDecorView().setSystemUiVisibility(visibility);
|
||||
}
|
||||
activity.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
|
||||
}
|
||||
|
@ -1813,6 +1807,10 @@ public class VideoDetailFragment
|
|||
return getResources().getDisplayMetrics().heightPixels < getResources().getDisplayMetrics().widthPixels;
|
||||
}
|
||||
|
||||
private boolean isInMultiWindow() {
|
||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && activity.isInMultiWindowMode();
|
||||
}
|
||||
|
||||
/*
|
||||
* Means that the player fragment was swiped away via BottomSheetLayout and is empty but ready for any new actions. See cleanUp()
|
||||
* */
|
||||
|
|
|
@ -26,6 +26,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
@ -183,7 +184,11 @@ public final class MainPlayer extends Service {
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
boolean isLandscape() {
|
||||
return getResources().getDisplayMetrics().heightPixels < getResources().getDisplayMetrics().widthPixels;
|
||||
// DisplayMetrics from activity context knows about MultiWindow feature while DisplayMetrics from app context doesn't
|
||||
final DisplayMetrics metrics = playerImpl.getParentActivity() != null ?
|
||||
playerImpl.getParentActivity().getResources().getDisplayMetrics()
|
||||
: getResources().getDisplayMetrics();
|
||||
return metrics.heightPixels < metrics.widthPixels;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
|
|
|
@ -38,11 +38,7 @@ import android.view.Menu;
|
|||
import android.view.MenuItem;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.*;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -131,7 +127,7 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
private TextView playbackLiveSync;
|
||||
private TextView playbackSpeedTextView;
|
||||
|
||||
private View topControlsRoot;
|
||||
private LinearLayout topControlsRoot;
|
||||
private TextView qualityTextView;
|
||||
|
||||
private SubtitleView subtitleView;
|
||||
|
@ -961,7 +957,7 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
return playbackEndTime;
|
||||
}
|
||||
|
||||
public View getTopControlsRoot() {
|
||||
public LinearLayout getTopControlsRoot() {
|
||||
return topControlsRoot;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import android.annotation.SuppressLint;
|
|||
import android.content.*;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
|
@ -124,7 +125,6 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
private ImageButton shareButton;
|
||||
|
||||
private View primaryControls;
|
||||
private LinearLayout topControls;
|
||||
private View secondaryControls;
|
||||
|
||||
private int maxGestureLength;
|
||||
|
@ -245,7 +245,6 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
|
||||
this.moreOptionsButton = rootView.findViewById(R.id.moreOptionsButton);
|
||||
this.primaryControls = rootView.findViewById(R.id.primaryControls);
|
||||
this.topControls = rootView.findViewById(R.id.topControls);
|
||||
this.secondaryControls = rootView.findViewById(R.id.secondaryControls);
|
||||
this.shareButton = rootView.findViewById(R.id.share);
|
||||
|
||||
|
@ -285,7 +284,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
getRootView().findViewById(R.id.metadataView).setVisibility(View.GONE);
|
||||
queueButton.setVisibility(View.GONE);
|
||||
moreOptionsButton.setVisibility(View.GONE);
|
||||
topControls.setOrientation(LinearLayout.HORIZONTAL);
|
||||
getTopControlsRoot().setOrientation(LinearLayout.HORIZONTAL);
|
||||
primaryControls.getLayoutParams().width = LinearLayout.LayoutParams.WRAP_CONTENT;
|
||||
secondaryControls.setAlpha(1f);
|
||||
secondaryControls.setVisibility(View.VISIBLE);
|
||||
|
@ -297,7 +296,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
fullscreenButton.setVisibility(View.GONE);
|
||||
getRootView().findViewById(R.id.metadataView).setVisibility(View.VISIBLE);
|
||||
moreOptionsButton.setVisibility(View.VISIBLE);
|
||||
topControls.setOrientation(LinearLayout.VERTICAL);
|
||||
getTopControlsRoot().setOrientation(LinearLayout.VERTICAL);
|
||||
primaryControls.getLayoutParams().width = LinearLayout.LayoutParams.MATCH_PARENT;
|
||||
secondaryControls.setVisibility(View.GONE);
|
||||
moreOptionsButton.setImageDrawable(service.getResources().getDrawable(
|
||||
|
@ -507,7 +506,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
|
||||
@Override
|
||||
public void toggleFullscreen() {
|
||||
if (DEBUG) Log.d(TAG, "onFullScreenButtonClicked() called");
|
||||
if (DEBUG) Log.d(TAG, "toggleFullscreen() called");
|
||||
if (simpleExoPlayer == null || getCurrentMetadata() == null) return;
|
||||
|
||||
if (popupPlayerSelected()) {
|
||||
|
@ -535,6 +534,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
if (fragmentListener == null) return;
|
||||
|
||||
isFullscreen = !isFullscreen;
|
||||
setControlsWidth();
|
||||
fragmentListener.onFullscreenStateChanged(isInFullscreen());
|
||||
// When user presses back button in landscape mode and in fullscreen and uses ZOOM mode
|
||||
// a video can be larger than screen. Prevent it like this
|
||||
|
@ -595,7 +595,8 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
getControlsVisibilityHandler().removeCallbacksAndMessages(null);
|
||||
animateView(getControlsRoot(), true, DEFAULT_CONTROLS_DURATION, 0, () -> {
|
||||
if (getCurrentState() == STATE_PLAYING && !isSomePopupMenuVisible()) {
|
||||
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||
if (v.getId() == playPauseButton.getId()) hideControls(0, 0);
|
||||
else hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -816,6 +817,8 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
service.getLockManager().acquireWifiAndCpu();
|
||||
service.resetNotification();
|
||||
service.updateNotification(R.drawable.ic_pause_white);
|
||||
|
||||
service.startForeground(NOTIFICATION_ID, service.getNotBuilder().build());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -831,6 +834,10 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
service.resetNotification();
|
||||
service.updateNotification(R.drawable.ic_play_arrow_white);
|
||||
|
||||
// Remove running notification when user don't want music (or video in popup) to be played in background
|
||||
if (!minimizeOnPopupEnabled() && !backgroundPlaybackEnabled() && videoPlayerSelected())
|
||||
service.stopForeground(true);
|
||||
|
||||
getRootView().setKeepScreenOn(false);
|
||||
|
||||
service.getLockManager().releaseWifiAndCpu();
|
||||
|
@ -1033,6 +1040,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
if (queueVisible) return;
|
||||
|
||||
showOrHideButtons();
|
||||
showSystemUIPartially();
|
||||
super.showControlsThenHide();
|
||||
}
|
||||
|
||||
|
@ -1041,6 +1049,7 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
if (queueVisible) return;
|
||||
|
||||
showOrHideButtons();
|
||||
showSystemUIPartially();
|
||||
super.showControls(duration);
|
||||
}
|
||||
|
||||
|
@ -1078,12 +1087,36 @@ public class VideoPlayerImpl extends VideoPlayer
|
|||
queueButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void showSystemUIPartially() {
|
||||
if (isInFullscreen()) {
|
||||
int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||
getParentActivity().getWindow().getDecorView().setSystemUiVisibility(visibility);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideSystemUIIfNeeded() {
|
||||
if (fragmentListener != null)
|
||||
fragmentListener.hideSystemUIIfNeeded();
|
||||
}
|
||||
|
||||
private void setControlsWidth() {
|
||||
Point size = new Point();
|
||||
// This method will give a correct size of a usable area of a window.
|
||||
// It doesn't include NavigationBar, notches, etc.
|
||||
getRootView().getDisplay().getSize(size);
|
||||
|
||||
int width = isFullscreen ? size.x : ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
primaryControls.getLayoutParams().width = width;
|
||||
primaryControls.requestLayout();
|
||||
secondaryControls.getLayoutParams().width = width;
|
||||
secondaryControls.requestLayout();
|
||||
getBottomControlsRoot().getLayoutParams().width = width;
|
||||
getBottomControlsRoot().requestLayout();
|
||||
}
|
||||
|
||||
private void updatePlaybackButtons() {
|
||||
if (repeatButton == null || shuffleButton == null ||
|
||||
simpleExoPlayer == null || playQueue == null) return;
|
||||
|
|
|
@ -18,27 +18,30 @@ public class CustomBottomSheetBehavior extends BottomSheetBehavior {
|
|||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent event) {
|
||||
// Behavior of globalVisibleRect is different on different APIs.
|
||||
// For example, on API 19 getGlobalVisibleRect returns a filled rect of a collapsed view while on the latest API
|
||||
// it returns empty rect in that case. So check visibility with return value too
|
||||
boolean visible;
|
||||
Rect rect = new Rect();
|
||||
|
||||
// Without overriding scrolling will not work in detail_content_root_layout
|
||||
ViewGroup controls = child.findViewById(R.id.detail_content_root_layout);
|
||||
if (controls != null) {
|
||||
Rect rect = new Rect();
|
||||
controls.getGlobalVisibleRect(rect);
|
||||
if (rect.contains((int) event.getX(), (int) event.getY())) return false;
|
||||
visible = controls.getGlobalVisibleRect(rect);
|
||||
if (rect.contains((int) event.getX(), (int) event.getY()) && visible) return false;
|
||||
}
|
||||
|
||||
// Without overriding scrolling will not work on relatedStreamsLayout
|
||||
ViewGroup relatedStreamsLayout = child.findViewById(R.id.relatedStreamsLayout);
|
||||
if (relatedStreamsLayout != null) {
|
||||
Rect rect = new Rect();
|
||||
relatedStreamsLayout.getGlobalVisibleRect(rect);
|
||||
if (rect.contains((int) event.getX(), (int) event.getY())) return false;
|
||||
visible = relatedStreamsLayout.getGlobalVisibleRect(rect);
|
||||
if (rect.contains((int) event.getX(), (int) event.getY()) && visible) return false;
|
||||
}
|
||||
|
||||
ViewGroup playQueue = child.findViewById(R.id.playQueue);
|
||||
if (playQueue != null) {
|
||||
Rect rect = new Rect();
|
||||
playQueue.getGlobalVisibleRect(rect);
|
||||
if (rect.contains((int) event.getX(), (int) event.getY())) return false;
|
||||
visible = playQueue.getGlobalVisibleRect(rect);
|
||||
if (rect.contains((int) event.getX(), (int) event.getY()) && visible) return false;
|
||||
}
|
||||
|
||||
return super.onInterceptTouchEvent(parent, child, event);
|
||||
|
|
|
@ -139,14 +139,6 @@ public class PlayerGestureListener extends GestureDetector.SimpleOnGestureListen
|
|||
} else {
|
||||
playerImpl.showControlsThenHide();
|
||||
}
|
||||
if (playerImpl.isInFullscreen()) {
|
||||
int visibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||
playerImpl.getParentActivity().getWindow().getDecorView().setSystemUiVisibility(visibility);
|
||||
playerImpl.getParentActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
|
||||
playerImpl.getParentActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -377,12 +377,17 @@
|
|||
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" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomControls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@drawable/player_controls_bg"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="6dp"
|
||||
|
|
|
@ -375,12 +375,17 @@
|
|||
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" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bottomControls"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="@drawable/player_controls_bg"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="6dp"
|
||||
|
|
|
@ -549,11 +549,10 @@
|
|||
android:layout_height="match_parent"
|
||||
android:alpha="0"
|
||||
tools:alpha="1"
|
||||
android:paddingLeft="@dimen/video_item_search_padding"
|
||||
android:paddingRight="@dimen/video_item_search_padding"
|
||||
android:background="?attr/windowBackground" >
|
||||
|
||||
<ImageButton
|
||||
android:paddingLeft="@dimen/video_item_search_padding"
|
||||
android:id="@+id/overlay_thumbnail"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="60dp"
|
||||
|
@ -613,6 +612,7 @@
|
|||
android:layout_height="60dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/video_item_search_padding"
|
||||
android:paddingRight="@dimen/video_item_search_padding"
|
||||
android:layout_alignParentEnd="true"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
|
|
Loading…
Reference in a new issue