Merge pull request #1597 from mauriciocolli/close-popup-overlay

New way to close the popup player
This commit is contained in:
Mauricio Colli 2018-08-23 23:56:41 -03:00 committed by GitHub
commit 78547aa119
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 270 additions and 92 deletions

View File

@ -19,6 +19,8 @@
package org.schabi.newpipe.player; package org.schabi.newpipe.player;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@ -34,6 +36,7 @@ import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
@ -41,7 +44,9 @@ import android.view.GestureDetector;
import android.view.Gravity; import android.view.Gravity;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.animation.AnticipateInterpolator;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.PopupMenu; import android.widget.PopupMenu;
@ -104,10 +109,13 @@ public final class PopupVideoPlayer extends Service {
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
private WindowManager windowManager; private WindowManager windowManager;
private WindowManager.LayoutParams windowLayoutParams; private WindowManager.LayoutParams popupLayoutParams;
private GestureDetector gestureDetector; private GestureDetector popupGestureDetector;
private View closeOverlayView;
private FloatingActionButton closeOverlayButton;
private WindowManager.LayoutParams closeOverlayLayoutParams;
private int shutdownFlingVelocity;
private int tossFlingVelocity; private int tossFlingVelocity;
private float screenWidth, screenHeight; private float screenWidth, screenHeight;
@ -122,6 +130,7 @@ public final class PopupVideoPlayer extends Service {
private VideoPlayerImpl playerImpl; private VideoPlayerImpl playerImpl;
private LockManager lockManager; private LockManager lockManager;
private boolean isPopupClosing = false;
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Service-Activity Binder // Service-Activity Binder
@ -150,7 +159,10 @@ public final class PopupVideoPlayer extends Service {
public int onStartCommand(final Intent intent, int flags, int startId) { public int onStartCommand(final Intent intent, int flags, int startId) {
if (DEBUG) if (DEBUG)
Log.d(TAG, "onStartCommand() called with: intent = [" + intent + "], flags = [" + flags + "], startId = [" + startId + "]"); Log.d(TAG, "onStartCommand() called with: intent = [" + intent + "], flags = [" + flags + "], startId = [" + startId + "]");
if (playerImpl.getPlayer() == null) initPopup(); if (playerImpl.getPlayer() == null) {
initPopup();
initPopupCloseOverlay();
}
if (!playerImpl.isPlaying()) playerImpl.getPlayer().setPlayWhenReady(true); if (!playerImpl.isPlaying()) playerImpl.getPlayer().setPlayWhenReady(true);
playerImpl.handleIntent(intent); playerImpl.handleIntent(intent);
@ -160,15 +172,16 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public void onConfigurationChanged(Configuration newConfig) { public void onConfigurationChanged(Configuration newConfig) {
if (DEBUG) Log.d(TAG, "onConfigurationChanged() called with: newConfig = [" + newConfig + "]");
updateScreenSize(); updateScreenSize();
updatePopupSize(windowLayoutParams.width, -1); updatePopupSize(popupLayoutParams.width, -1);
checkPositionBounds(); checkPopupPositionBounds();
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
if (DEBUG) Log.d(TAG, "onDestroy() called"); if (DEBUG) Log.d(TAG, "onDestroy() called");
onClose(); closePopup();
} }
@Override @Override
@ -186,7 +199,6 @@ public final class PopupVideoPlayer extends Service {
View rootView = View.inflate(this, R.layout.player_popup, null); View rootView = View.inflate(this, R.layout.player_popup, null);
playerImpl.setup(rootView); playerImpl.setup(rootView);
shutdownFlingVelocity = PlayerHelper.getShutdownFlingVelocity(this);
tossFlingVelocity = PlayerHelper.getTossFlingVelocity(this); tossFlingVelocity = PlayerHelper.getTossFlingVelocity(this);
updateScreenSize(); updateScreenSize();
@ -200,27 +212,52 @@ public final class PopupVideoPlayer extends Service {
WindowManager.LayoutParams.TYPE_PHONE : WindowManager.LayoutParams.TYPE_PHONE :
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
windowLayoutParams = new WindowManager.LayoutParams( popupLayoutParams = new WindowManager.LayoutParams(
(int) popupWidth, (int) getMinimumVideoHeight(popupWidth), (int) popupWidth, (int) getMinimumVideoHeight(popupWidth),
layoutParamType, layoutParamType,
IDLE_WINDOW_FLAGS, IDLE_WINDOW_FLAGS,
PixelFormat.TRANSLUCENT); PixelFormat.TRANSLUCENT);
windowLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; popupLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; popupLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
int centerX = (int) (screenWidth / 2f - popupWidth / 2f); int centerX = (int) (screenWidth / 2f - popupWidth / 2f);
int centerY = (int) (screenHeight / 2f - popupHeight / 2f); int centerY = (int) (screenHeight / 2f - popupHeight / 2f);
windowLayoutParams.x = popupRememberSizeAndPos ? sharedPreferences.getInt(POPUP_SAVED_X, centerX) : centerX; popupLayoutParams.x = popupRememberSizeAndPos ? sharedPreferences.getInt(POPUP_SAVED_X, centerX) : centerX;
windowLayoutParams.y = popupRememberSizeAndPos ? sharedPreferences.getInt(POPUP_SAVED_Y, centerY) : centerY; popupLayoutParams.y = popupRememberSizeAndPos ? sharedPreferences.getInt(POPUP_SAVED_Y, centerY) : centerY;
checkPositionBounds(); checkPopupPositionBounds();
MySimpleOnGestureListener listener = new MySimpleOnGestureListener(); PopupWindowGestureListener listener = new PopupWindowGestureListener();
gestureDetector = new GestureDetector(this, listener); popupGestureDetector = new GestureDetector(this, listener);
rootView.setOnTouchListener(listener); rootView.setOnTouchListener(listener);
playerImpl.getLoadingPanel().setMinimumWidth(windowLayoutParams.width);
playerImpl.getLoadingPanel().setMinimumHeight(windowLayoutParams.height); playerImpl.getLoadingPanel().setMinimumWidth(popupLayoutParams.width);
windowManager.addView(rootView, windowLayoutParams); playerImpl.getLoadingPanel().setMinimumHeight(popupLayoutParams.height);
windowManager.addView(rootView, popupLayoutParams);
}
@SuppressLint("RtlHardcoded")
private void initPopupCloseOverlay() {
if (DEBUG) Log.d(TAG, "initPopupCloseOverlay() called");
closeOverlayView = View.inflate(this, R.layout.player_popup_close_overlay, null);
closeOverlayButton = closeOverlayView.findViewById(R.id.closeButton);
final int layoutParamType = Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O ?
WindowManager.LayoutParams.TYPE_PHONE :
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
closeOverlayLayoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
layoutParamType,
flags,
PixelFormat.TRANSLUCENT);
closeOverlayLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
closeOverlayLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
closeOverlayButton.setVisibility(View.GONE);
windowManager.addView(closeOverlayView, closeOverlayLayoutParams);
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -280,44 +317,105 @@ public final class PopupVideoPlayer extends Service {
// Misc // Misc
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
public void onClose() { public void closePopup() {
if (DEBUG) Log.d(TAG, "onClose() called"); if (DEBUG) Log.d(TAG, "closePopup() called, isPopupClosing = " + isPopupClosing);
if (isPopupClosing) return;
isPopupClosing = true;
if (playerImpl != null) { if (playerImpl != null) {
if (playerImpl.getRootView() != null) { if (playerImpl.getRootView() != null) {
windowManager.removeView(playerImpl.getRootView()); windowManager.removeView(playerImpl.getRootView());
playerImpl.setRootView(null);
} }
playerImpl.setRootView(null);
playerImpl.stopActivityBinding(); playerImpl.stopActivityBinding();
playerImpl.destroy(); playerImpl.destroy();
playerImpl = null;
} }
mBinder = null;
if (lockManager != null) lockManager.releaseWifiAndCpu(); if (lockManager != null) lockManager.releaseWifiAndCpu();
if (notificationManager != null) notificationManager.cancel(NOTIFICATION_ID); if (notificationManager != null) notificationManager.cancel(NOTIFICATION_ID);
mBinder = null;
playerImpl = null;
stopForeground(true); animateOverlayAndFinishService();
stopSelf(); }
private void animateOverlayAndFinishService() {
final int targetTranslationY = (int) (closeOverlayButton.getRootView().getHeight() - closeOverlayButton.getY());
closeOverlayButton.animate().setListener(null).cancel();
closeOverlayButton.animate()
.setInterpolator(new AnticipateInterpolator())
.translationY(targetTranslationY)
.setDuration(400)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
end();
}
@Override
public void onAnimationEnd(Animator animation) {
end();
}
private void end() {
windowManager.removeView(closeOverlayView);
stopForeground(true);
stopSelf();
}
}).start();
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Utils // Utils
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private void checkPositionBounds() { /**
if (windowLayoutParams.x > screenWidth - windowLayoutParams.width) * @see #checkPopupPositionBounds(float, float)
windowLayoutParams.x = (int) (screenWidth - windowLayoutParams.width); */
if (windowLayoutParams.x < 0) windowLayoutParams.x = 0; @SuppressWarnings("UnusedReturnValue")
if (windowLayoutParams.y > screenHeight - windowLayoutParams.height) private boolean checkPopupPositionBounds() {
windowLayoutParams.y = (int) (screenHeight - windowLayoutParams.height); return checkPopupPositionBounds(screenWidth, screenHeight);
if (windowLayoutParams.y < 0) windowLayoutParams.y = 0; }
/**
* Check if {@link #popupLayoutParams}' position is within a arbitrary boundary that goes from (0,0) to (boundaryWidth,boundaryHeight).
* <p>
* If it's out of these boundaries, {@link #popupLayoutParams}' position is changed and {@code true} is returned
* to represent this change.
*
* @return if the popup was out of bounds and have been moved back to it
*/
private boolean checkPopupPositionBounds(final float boundaryWidth, final float boundaryHeight) {
if (DEBUG) {
Log.d(TAG, "checkPopupPositionBounds() called with: boundaryWidth = [" + boundaryWidth + "], boundaryHeight = [" + boundaryHeight + "]");
}
if (popupLayoutParams.x < 0) {
popupLayoutParams.x = 0;
return true;
} else if (popupLayoutParams.x > boundaryWidth - popupLayoutParams.width) {
popupLayoutParams.x = (int) (boundaryWidth - popupLayoutParams.width);
return true;
}
if (popupLayoutParams.y < 0) {
popupLayoutParams.y = 0;
return true;
} else if (popupLayoutParams.y > boundaryHeight - popupLayoutParams.height) {
popupLayoutParams.y = (int) (boundaryHeight - popupLayoutParams.height);
return true;
}
return false;
} }
private void savePositionAndSize() { private void savePositionAndSize() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(PopupVideoPlayer.this); SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(PopupVideoPlayer.this);
sharedPreferences.edit().putInt(POPUP_SAVED_X, windowLayoutParams.x).apply(); sharedPreferences.edit().putInt(POPUP_SAVED_X, popupLayoutParams.x).apply();
sharedPreferences.edit().putInt(POPUP_SAVED_Y, windowLayoutParams.y).apply(); sharedPreferences.edit().putInt(POPUP_SAVED_Y, popupLayoutParams.y).apply();
sharedPreferences.edit().putFloat(POPUP_SAVED_WIDTH, windowLayoutParams.width).apply(); sharedPreferences.edit().putFloat(POPUP_SAVED_WIDTH, popupLayoutParams.width).apply();
} }
private float getMinimumVideoHeight(float width) { private float getMinimumVideoHeight(float width) {
@ -352,13 +450,13 @@ public final class PopupVideoPlayer extends Service {
if (height == -1) height = (int) getMinimumVideoHeight(width); if (height == -1) height = (int) getMinimumVideoHeight(width);
else height = (int) (height > maximumHeight ? maximumHeight : height < minimumHeight ? minimumHeight : height); else height = (int) (height > maximumHeight ? maximumHeight : height < minimumHeight ? minimumHeight : height);
windowLayoutParams.width = width; popupLayoutParams.width = width;
windowLayoutParams.height = height; popupLayoutParams.height = height;
popupWidth = width; popupWidth = width;
popupHeight = height; popupHeight = height;
if (DEBUG) Log.d(TAG, "updatePopupSize() updated values: width = [" + width + "], height = [" + height + "]"); if (DEBUG) Log.d(TAG, "updatePopupSize() updated values: width = [" + width + "], height = [" + height + "]");
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams); windowManager.updateViewLayout(playerImpl.getRootView(), popupLayoutParams);
} }
protected void setRepeatModeRemote(final RemoteViews remoteViews, final int repeatMode) { protected void setRepeatModeRemote(final RemoteViews remoteViews, final int repeatMode) {
@ -380,10 +478,10 @@ public final class PopupVideoPlayer extends Service {
} }
private void updateWindowFlags(final int flags) { private void updateWindowFlags(final int flags) {
if (windowLayoutParams == null || windowManager == null || playerImpl == null) return; if (popupLayoutParams == null || windowManager == null || playerImpl == null) return;
windowLayoutParams.flags = flags; popupLayoutParams.flags = flags;
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams); windowManager.updateViewLayout(playerImpl.getRootView(), popupLayoutParams);
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@ -393,6 +491,7 @@ public final class PopupVideoPlayer extends Service {
private ImageView videoPlayPause; private ImageView videoPlayPause;
private View extraOptionsView; private View extraOptionsView;
private View closingOverlayView;
@Override @Override
public void handleIntent(Intent intent) { public void handleIntent(Intent intent) {
@ -413,12 +512,18 @@ public final class PopupVideoPlayer extends Service {
fullScreenButton = rootView.findViewById(R.id.fullScreenButton); fullScreenButton = rootView.findViewById(R.id.fullScreenButton);
fullScreenButton.setOnClickListener(v -> onFullScreenButtonClicked()); fullScreenButton.setOnClickListener(v -> onFullScreenButtonClicked());
videoPlayPause = rootView.findViewById(R.id.videoPlayPause); videoPlayPause = rootView.findViewById(R.id.videoPlayPause);
videoPlayPause.setOnClickListener(this::onPlayPauseButtonPressed);
extraOptionsView = rootView.findViewById(R.id.extraOptionsView); extraOptionsView = rootView.findViewById(R.id.extraOptionsView);
closingOverlayView = rootView.findViewById(R.id.closingOverlay);
rootView.addOnLayoutChangeListener(this); rootView.addOnLayoutChangeListener(this);
} }
@Override
public void initListeners() {
super.initListeners();
videoPlayPause.setOnClickListener(v -> onPlayPause());
}
@Override @Override
protected void setupSubtitleView(@NonNull SubtitleView view, protected void setupSubtitleView(@NonNull SubtitleView view,
final float captionScale, final float captionScale,
@ -429,10 +534,6 @@ public final class PopupVideoPlayer extends Service {
view.setStyle(captionStyle); view.setStyle(captionStyle);
} }
private void onPlayPauseButtonPressed(View ib) {
onPlayPause();
}
@Override @Override
public void onLayoutChange(final View view, int left, int top, int right, int bottom, public void onLayoutChange(final View view, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) { int oldLeft, int oldTop, int oldRight, int oldBottom) {
@ -476,7 +577,7 @@ public final class PopupVideoPlayer extends Service {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} }
context.startActivity(intent); context.startActivity(intent);
onClose(); closePopup();
} }
@Override @Override
@ -634,7 +735,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public void onPlaybackShutdown() { public void onPlaybackShutdown() {
super.onPlaybackShutdown(); super.onPlaybackShutdown();
onClose(); closePopup();
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -660,7 +761,7 @@ public final class PopupVideoPlayer extends Service {
if (DEBUG) Log.d(TAG, "onBroadcastReceived() called with: intent = [" + intent + "]"); if (DEBUG) Log.d(TAG, "onBroadcastReceived() called with: intent = [" + intent + "]");
switch (intent.getAction()) { switch (intent.getAction()) {
case ACTION_CLOSE: case ACTION_CLOSE:
onClose(); closePopup();
break; break;
case ACTION_PLAY_PAUSE: case ACTION_PLAY_PAUSE:
onPlayPause(); onPlayPause();
@ -791,12 +892,15 @@ public final class PopupVideoPlayer extends Service {
public TextView getResizingIndicator() { public TextView getResizingIndicator() {
return resizingIndicator; return resizingIndicator;
} }
public View getClosingOverlayView() {
return closingOverlayView;
}
} }
private class MySimpleOnGestureListener extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener { private class PopupWindowGestureListener extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener {
private int initialPopupX, initialPopupY; private int initialPopupX, initialPopupY;
private boolean isMoving; private boolean isMoving;
private boolean isResizing; private boolean isResizing;
@Override @Override
@ -832,10 +936,15 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public boolean onDown(MotionEvent e) { public boolean onDown(MotionEvent e) {
if (DEBUG) Log.d(TAG, "onDown() called with: e = [" + e + "]"); if (DEBUG) Log.d(TAG, "onDown() called with: e = [" + e + "]");
initialPopupX = windowLayoutParams.x;
initialPopupY = windowLayoutParams.y; // Fix popup position when the user touch it, it may have the wrong one
popupWidth = windowLayoutParams.width; // because the soft input is visible (the draggable area is currently resized).
popupHeight = windowLayoutParams.height; checkPopupPositionBounds(closeOverlayView.getWidth(), closeOverlayView.getHeight());
initialPopupX = popupLayoutParams.x;
initialPopupY = popupLayoutParams.y;
popupWidth = popupLayoutParams.width;
popupHeight = popupLayoutParams.height;
return super.onDown(e); return super.onDown(e);
} }
@ -843,20 +952,22 @@ public final class PopupVideoPlayer extends Service {
public void onLongPress(MotionEvent e) { public void onLongPress(MotionEvent e) {
if (DEBUG) Log.d(TAG, "onLongPress() called with: e = [" + e + "]"); if (DEBUG) Log.d(TAG, "onLongPress() called with: e = [" + e + "]");
updateScreenSize(); updateScreenSize();
checkPositionBounds(); checkPopupPositionBounds();
updatePopupSize((int) screenWidth, -1); updatePopupSize((int) screenWidth, -1);
} }
@Override @Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { public boolean onScroll(MotionEvent initialEvent, MotionEvent movingEvent, float distanceX, float distanceY) {
if (isResizing || playerImpl == null) return super.onScroll(e1, e2, distanceX, distanceY); if (isResizing || playerImpl == null) return super.onScroll(initialEvent, movingEvent, distanceX, distanceY);
if (!isMoving) {
animateView(closeOverlayButton, true, 200);
}
if (playerImpl.getCurrentState() != BasePlayer.STATE_BUFFERING
&& (!isMoving || playerImpl.getControlsRoot().getAlpha() != 1f)) playerImpl.showControls(0);
isMoving = true; isMoving = true;
float diffX = (int) (e2.getRawX() - e1.getRawX()), posX = (int) (initialPopupX + diffX); float diffX = (int) (movingEvent.getRawX() - initialEvent.getRawX()), posX = (int) (initialPopupX + diffX);
float diffY = (int) (e2.getRawY() - e1.getRawY()), posY = (int) (initialPopupY + diffY); float diffY = (int) (movingEvent.getRawY() - initialEvent.getRawY()), posY = (int) (initialPopupY + diffY);
if (posX > (screenWidth - popupWidth)) posX = (int) (screenWidth - popupWidth); if (posX > (screenWidth - popupWidth)) posX = (int) (screenWidth - popupWidth);
else if (posX < 0) posX = 0; else if (posX < 0) posX = 0;
@ -864,26 +975,49 @@ public final class PopupVideoPlayer extends Service {
if (posY > (screenHeight - popupHeight)) posY = (int) (screenHeight - popupHeight); if (posY > (screenHeight - popupHeight)) posY = (int) (screenHeight - popupHeight);
else if (posY < 0) posY = 0; else if (posY < 0) posY = 0;
windowLayoutParams.x = (int) posX; popupLayoutParams.x = (int) posX;
windowLayoutParams.y = (int) posY; popupLayoutParams.y = (int) posY;
final View closingOverlayView = playerImpl.getClosingOverlayView();
if (isInsideClosingRadius(movingEvent)) {
if (closingOverlayView.getVisibility() == View.GONE) {
animateView(closingOverlayView, true, 250);
}
} else {
if (closingOverlayView.getVisibility() == View.VISIBLE) {
animateView(closingOverlayView, false, 0);
}
}
//noinspection PointlessBooleanExpression //noinspection PointlessBooleanExpression
if (DEBUG && false) Log.d(TAG, "PopupVideoPlayer.onScroll = " + if (DEBUG && false) {
", e1.getRaw = [" + e1.getRawX() + ", " + e1.getRawY() + "]" + Log.d(TAG, "PopupVideoPlayer.onScroll = " +
", e2.getRaw = [" + e2.getRawX() + ", " + e2.getRawY() + "]" + ", e1.getRaw = [" + initialEvent.getRawX() + ", " + initialEvent.getRawY() + "]" + ", e1.getX,Y = [" + initialEvent.getX() + ", " + initialEvent.getY() + "]" +
", distanceXy = [" + distanceX + ", " + distanceY + "]" + ", e2.getRaw = [" + movingEvent.getRawX() + ", " + movingEvent.getRawY() + "]" + ", e2.getX,Y = [" + movingEvent.getX() + ", " + movingEvent.getY() + "]" +
", posXy = [" + posX + ", " + posY + "]" + ", distanceX,Y = [" + distanceX + ", " + distanceY + "]" +
", popupWh = [" + popupWidth + " x " + popupHeight + "]"); ", posX,Y = [" + posX + ", " + posY + "]" +
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams); ", popupW,H = [" + popupWidth + " x " + popupHeight + "]");
}
windowManager.updateViewLayout(playerImpl.getRootView(), popupLayoutParams);
return true; return true;
} }
private void onScrollEnd() { private void onScrollEnd(MotionEvent event) {
if (DEBUG) Log.d(TAG, "onScrollEnd() called"); if (DEBUG) Log.d(TAG, "onScrollEnd() called");
if (playerImpl == null) return; if (playerImpl == null) return;
if (playerImpl.isControlsVisible() && playerImpl.getCurrentState() == STATE_PLAYING) { if (playerImpl.isControlsVisible() && playerImpl.getCurrentState() == STATE_PLAYING) {
playerImpl.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME); playerImpl.hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
} }
if (isInsideClosingRadius(event)) {
closePopup();
} else {
animateView(playerImpl.getClosingOverlayView(), false, 0);
if (!isPopupClosing) {
animateView(closeOverlayButton, false, 200);
}
}
} }
@Override @Override
@ -893,14 +1027,11 @@ public final class PopupVideoPlayer extends Service {
final float absVelocityX = Math.abs(velocityX); final float absVelocityX = Math.abs(velocityX);
final float absVelocityY = Math.abs(velocityY); final float absVelocityY = Math.abs(velocityY);
if (absVelocityX > shutdownFlingVelocity) { if (Math.max(absVelocityX, absVelocityY) > tossFlingVelocity) {
onClose(); if (absVelocityX > tossFlingVelocity) popupLayoutParams.x = (int) velocityX;
return true; if (absVelocityY > tossFlingVelocity) popupLayoutParams.y = (int) velocityY;
} else if (Math.max(absVelocityX, absVelocityY) > tossFlingVelocity) { checkPopupPositionBounds();
if (absVelocityX > tossFlingVelocity) windowLayoutParams.x = (int) velocityX; windowManager.updateViewLayout(playerImpl.getRootView(), popupLayoutParams);
if (absVelocityY > tossFlingVelocity) windowLayoutParams.y = (int) velocityY;
checkPositionBounds();
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams);
return true; return true;
} }
return false; return false;
@ -908,7 +1039,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public boolean onTouch(View v, MotionEvent event) { public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event); popupGestureDetector.onTouchEvent(event);
if (playerImpl == null) return false; if (playerImpl == null) return false;
if (event.getPointerCount() == 2 && !isResizing) { if (event.getPointerCount() == 2 && !isResizing) {
if (DEBUG) Log.d(TAG, "onTouch() 2 finger pointer detected, enabling resizing."); if (DEBUG) Log.d(TAG, "onTouch() 2 finger pointer detected, enabling resizing.");
@ -931,7 +1062,7 @@ public final class PopupVideoPlayer extends Service {
Log.d(TAG, "onTouch() ACTION_UP > v = [" + v + "], e1.getRaw = [" + event.getRawX() + ", " + event.getRawY() + "]"); Log.d(TAG, "onTouch() ACTION_UP > v = [" + v + "], e1.getRaw = [" + event.getRawX() + ", " + event.getRawY() + "]");
if (isMoving) { if (isMoving) {
isMoving = false; isMoving = false;
onScrollEnd(); onScrollEnd(event);
} }
if (isResizing) { if (isResizing) {
@ -939,7 +1070,10 @@ public final class PopupVideoPlayer extends Service {
animateView(playerImpl.getResizingIndicator(), false, 100, 0); animateView(playerImpl.getResizingIndicator(), false, 100, 0);
playerImpl.changeState(playerImpl.getCurrentState()); playerImpl.changeState(playerImpl.getCurrentState());
} }
savePositionAndSize();
if (!isPopupClosing) {
savePositionAndSize();
}
} }
v.performClick(); v.performClick();
@ -955,13 +1089,13 @@ public final class PopupVideoPlayer extends Service {
final float diff = Math.abs(firstPointerX - secondPointerX); final float diff = Math.abs(firstPointerX - secondPointerX);
if (firstPointerX > secondPointerX) { if (firstPointerX > secondPointerX) {
// second pointer is the anchor (the leftmost pointer) // second pointer is the anchor (the leftmost pointer)
windowLayoutParams.x = (int) (event.getRawX() - diff); popupLayoutParams.x = (int) (event.getRawX() - diff);
} else { } else {
// first pointer is the anchor // first pointer is the anchor
windowLayoutParams.x = (int) event.getRawX(); popupLayoutParams.x = (int) event.getRawX();
} }
checkPositionBounds(); checkPopupPositionBounds();
updateScreenSize(); updateScreenSize();
final int width = (int) Math.min(screenWidth, diff); final int width = (int) Math.min(screenWidth, diff);
@ -969,5 +1103,29 @@ public final class PopupVideoPlayer extends Service {
return true; return true;
} }
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
private int distanceFromCloseButton(MotionEvent popupMotionEvent) {
final int closeOverlayButtonX = closeOverlayButton.getLeft() + closeOverlayButton.getWidth() / 2;
final int closeOverlayButtonY = closeOverlayButton.getTop() + closeOverlayButton.getHeight() / 2;
float fingerX = popupLayoutParams.x + popupMotionEvent.getX();
float fingerY = popupLayoutParams.y + popupMotionEvent.getY();
return (int) Math.sqrt(Math.pow(closeOverlayButtonX - fingerX, 2) + Math.pow(closeOverlayButtonY - fingerY, 2));
}
private float getClosingRadius() {
final int buttonRadius = closeOverlayButton.getWidth() / 2;
// 20% wider than the button itself
return buttonRadius * 1.2f;
}
private boolean isInsideClosingRadius(MotionEvent popupMotionEvent) {
return distanceFromCloseButton(popupMotionEvent) <= getClosingRadius();
}
} }
} }

View File

@ -251,10 +251,6 @@ public class PlayerHelper {
return true; return true;
} }
public static int getShutdownFlingVelocity(@NonNull final Context context) {
return 6000;
}
public static int getTossFlingVelocity(@NonNull final Context context) { public static int getTossFlingVelocity(@NonNull final Context context) {
return 2500; return 2500;
} }

View File

@ -9,7 +9,6 @@
tools:layout_height="84dp" tools:layout_height="84dp"
tools:layout_width="@dimen/popup_minimum_width"> tools:layout_width="@dimen/popup_minimum_width">
<com.google.android.exoplayer2.ui.AspectRatioFrameLayout <com.google.android.exoplayer2.ui.AspectRatioFrameLayout
android:id="@+id/aspectRatioLayout" android:id="@+id/aspectRatioLayout"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -290,4 +289,11 @@
android:visibility="gone" android:visibility="gone"
tools:ignore="RtlHardcoded" tools:ignore="RtlHardcoded"
tools:visibility="gone"/> tools:visibility="gone"/>
<View
android:id="@+id/closingOverlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#AAFF0000"
android:visibility="gone"/>
</FrameLayout> </FrameLayout>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
android:id="@+id/closeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="24dp"
android:src="@drawable/ic_close_white_24dp"
app:backgroundTint="@color/light_youtube_primary_color"
app:borderWidth="0dp"
app:fabSize="normal"/>
</FrameLayout>