Add overlay to close popup

This commit is contained in:
Mauricio Colli 2018-08-21 23:04:46 -03:00
parent 607ca84fcc
commit 69fc571b56
No known key found for this signature in database
GPG Key ID: F200BFD6F29DDD85
3 changed files with 231 additions and 75 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,8 +109,12 @@ 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 shutdownFlingVelocity;
private int tossFlingVelocity; private int tossFlingVelocity;
@ -122,6 +131,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 +160,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 +173,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(); checkPositionBounds();
} }
@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
@ -200,27 +214,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(); checkPositionBounds();
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 +319,76 @@ 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; animateOverlayAndFinishService();
}
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); stopForeground(true);
stopSelf(); stopSelf();
} }
}).start();
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Utils // Utils
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private void checkPositionBounds() { private void checkPositionBounds() {
if (windowLayoutParams.x > screenWidth - windowLayoutParams.width) if (DEBUG) Log.d(TAG, "checkPositionBounds() called");
windowLayoutParams.x = (int) (screenWidth - windowLayoutParams.width); if (popupLayoutParams.x > screenWidth - popupLayoutParams.width)
if (windowLayoutParams.x < 0) windowLayoutParams.x = 0; popupLayoutParams.x = (int) (screenWidth - popupLayoutParams.width);
if (windowLayoutParams.y > screenHeight - windowLayoutParams.height) if (popupLayoutParams.x < 0) popupLayoutParams.x = 0;
windowLayoutParams.y = (int) (screenHeight - windowLayoutParams.height);
if (windowLayoutParams.y < 0) windowLayoutParams.y = 0; if (popupLayoutParams.y > screenHeight - popupLayoutParams.height)
popupLayoutParams.y = (int) (screenHeight - popupLayoutParams.height);
if (popupLayoutParams.y < 0) popupLayoutParams.y = 0;
} }
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 +423,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 +451,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 +464,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 +485,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 +507,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 +550,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 +708,7 @@ public final class PopupVideoPlayer extends Service {
@Override @Override
public void onPlaybackShutdown() { public void onPlaybackShutdown() {
super.onPlaybackShutdown(); super.onPlaybackShutdown();
onClose(); closePopup();
} }
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
@ -660,7 +734,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 +865,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 +909,10 @@ 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; initialPopupX = popupLayoutParams.x;
initialPopupY = windowLayoutParams.y; initialPopupY = popupLayoutParams.y;
popupWidth = windowLayoutParams.width; popupWidth = popupLayoutParams.width;
popupHeight = windowLayoutParams.height; popupHeight = popupLayoutParams.height;
return super.onDown(e); return super.onDown(e);
} }
@ -848,15 +925,20 @@ public final class PopupVideoPlayer extends Service {
} }
@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 (playerImpl.getCurrentState() != BasePlayer.STATE_BUFFERING if (playerImpl.getCurrentState() != BasePlayer.STATE_BUFFERING
&& (!isMoving || playerImpl.getControlsRoot().getAlpha() != 1f)) playerImpl.showControls(0); && (!isMoving || playerImpl.getControlsRoot().getAlpha() != 1f)) playerImpl.showControls(0);
if (!isMoving) {
animateView(closeOverlayButton, true, 200);
}
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 +946,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
@ -894,13 +999,13 @@ 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 (absVelocityX > shutdownFlingVelocity) {
onClose(); closePopup();
return true; return true;
} else if (Math.max(absVelocityX, absVelocityY) > tossFlingVelocity) { } else if (Math.max(absVelocityX, absVelocityY) > tossFlingVelocity) {
if (absVelocityX > tossFlingVelocity) windowLayoutParams.x = (int) velocityX; if (absVelocityX > tossFlingVelocity) popupLayoutParams.x = (int) velocityX;
if (absVelocityY > tossFlingVelocity) windowLayoutParams.y = (int) velocityY; if (absVelocityY > tossFlingVelocity) popupLayoutParams.y = (int) velocityY;
checkPositionBounds(); checkPositionBounds();
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams); windowManager.updateViewLayout(playerImpl.getRootView(), popupLayoutParams);
return true; return true;
} }
return false; return false;
@ -908,7 +1013,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 +1036,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,8 +1044,11 @@ 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());
} }
if (!isPopupClosing) {
savePositionAndSize(); savePositionAndSize();
} }
}
v.performClick(); v.performClick();
return true; return true;
@ -955,10 +1063,10 @@ 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(); checkPositionBounds();
@ -969,5 +1077,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

@ -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>