mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 08:30:44 +00:00
Move popup layout param to PopupPlayerUi
This commit is contained in:
parent
9c51fc3ade
commit
3692858a3d
@ -7,7 +7,6 @@ import android.view.ViewConfiguration
|
||||
import org.schabi.newpipe.MainActivity
|
||||
import org.schabi.newpipe.ktx.AnimationType
|
||||
import org.schabi.newpipe.ktx.animate
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper
|
||||
import org.schabi.newpipe.player.ui.PopupPlayerUi
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.hypot
|
||||
@ -87,7 +86,7 @@ class PopupPlayerGestureListener(
|
||||
player.changeState(player.currentState)
|
||||
}
|
||||
if (!playerUi.isPopupClosing) {
|
||||
PlayerHelper.savePopupPositionAndSizeToPrefs(playerUi)
|
||||
playerUi.savePopupPositionAndSizeToPrefs()
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,40 +105,42 @@ class PopupPlayerGestureListener(
|
||||
}
|
||||
|
||||
private fun handleMultiDrag(event: MotionEvent): Boolean {
|
||||
if (initPointerDistance != -1.0 && event.pointerCount == 2) {
|
||||
// get the movements of the fingers
|
||||
val firstPointerMove = hypot(
|
||||
event.getX(0) - initFirstPointerX.toDouble(),
|
||||
event.getY(0) - initFirstPointerY.toDouble()
|
||||
)
|
||||
val secPointerMove = hypot(
|
||||
event.getX(1) - initSecPointerX.toDouble(),
|
||||
event.getY(1) - initSecPointerY.toDouble()
|
||||
)
|
||||
|
||||
// minimum threshold beyond which pinch gesture will work
|
||||
val minimumMove = ViewConfiguration.get(player.context).scaledTouchSlop
|
||||
|
||||
if (max(firstPointerMove, secPointerMove) > minimumMove) {
|
||||
// calculate current distance between the pointers
|
||||
val currentPointerDistance = hypot(
|
||||
event.getX(0) - event.getX(1).toDouble(),
|
||||
event.getY(0) - event.getY(1).toDouble()
|
||||
)
|
||||
|
||||
val popupWidth = playerUi.popupLayoutParams.width.toDouble()
|
||||
// change co-ordinates of popup so the center stays at the same position
|
||||
val newWidth = popupWidth * currentPointerDistance / initPointerDistance
|
||||
initPointerDistance = currentPointerDistance
|
||||
playerUi.popupLayoutParams.x += ((popupWidth - newWidth) / 2.0).toInt()
|
||||
|
||||
playerUi.checkPopupPositionBounds()
|
||||
playerUi.updateScreenSize()
|
||||
playerUi.changePopupSize(min(playerUi.screenWidth.toDouble(), newWidth).toInt())
|
||||
return true
|
||||
}
|
||||
if (initPointerDistance == -1.0 || event.pointerCount != 2) {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
|
||||
// get the movements of the fingers
|
||||
val firstPointerMove = hypot(
|
||||
event.getX(0) - initFirstPointerX.toDouble(),
|
||||
event.getY(0) - initFirstPointerY.toDouble()
|
||||
)
|
||||
val secPointerMove = hypot(
|
||||
event.getX(1) - initSecPointerX.toDouble(),
|
||||
event.getY(1) - initSecPointerY.toDouble()
|
||||
)
|
||||
|
||||
// minimum threshold beyond which pinch gesture will work
|
||||
val minimumMove = ViewConfiguration.get(player.context).scaledTouchSlop
|
||||
if (max(firstPointerMove, secPointerMove) <= minimumMove) {
|
||||
return false
|
||||
}
|
||||
|
||||
// calculate current distance between the pointers
|
||||
val currentPointerDistance = hypot(
|
||||
event.getX(0) - event.getX(1).toDouble(),
|
||||
event.getY(0) - event.getY(1).toDouble()
|
||||
)
|
||||
|
||||
val popupWidth = playerUi.popupLayoutParams.width.toDouble()
|
||||
// change co-ordinates of popup so the center stays at the same position
|
||||
val newWidth = popupWidth * currentPointerDistance / initPointerDistance
|
||||
initPointerDistance = currentPointerDistance
|
||||
playerUi.popupLayoutParams.x += ((popupWidth - newWidth) / 2.0).toInt()
|
||||
|
||||
playerUi.checkPopupPositionBounds()
|
||||
playerUi.updateScreenSize()
|
||||
playerUi.changePopupSize(min(playerUi.screenWidth.toDouble(), newWidth).toInt())
|
||||
return true
|
||||
}
|
||||
|
||||
private fun onPopupResizingStart() {
|
||||
|
@ -10,19 +10,13 @@ import static org.schabi.newpipe.player.helper.PlayerHelper.AutoplayType.AUTOPLA
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_BACKGROUND;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_NONE;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.MinimizeMode.MINIMIZE_ON_EXIT_MODE_POPUP;
|
||||
import static org.schabi.newpipe.player.ui.PopupPlayerUi.IDLE_WINDOW_FLAGS;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.view.Gravity;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.CaptioningManager;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
@ -49,12 +43,11 @@ import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.SubtitlesStream;
|
||||
import org.schabi.newpipe.extractor.utils.Utils;
|
||||
import org.schabi.newpipe.player.PlayerService;
|
||||
import org.schabi.newpipe.player.Player;
|
||||
import org.schabi.newpipe.player.PlayerService;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||
import org.schabi.newpipe.player.ui.PopupPlayerUi;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@ -77,20 +70,6 @@ public final class PlayerHelper {
|
||||
private static final NumberFormat SPEED_FORMATTER = new DecimalFormat("0.##x");
|
||||
private static final NumberFormat PITCH_FORMATTER = new DecimalFormat("##%");
|
||||
|
||||
/**
|
||||
* Maximum opacity allowed for Android 12 and higher to allow touches on other apps when using
|
||||
* NewPipe's popup player.
|
||||
*
|
||||
* <p>
|
||||
* This value is hardcoded instead of being get dynamically with the method linked of the
|
||||
* constant documentation below, because it is not static and popup player layout parameters
|
||||
* are generated with static methods.
|
||||
* </p>
|
||||
*
|
||||
* @see WindowManager.LayoutParams#FLAG_NOT_TOUCHABLE
|
||||
*/
|
||||
private static final float MAXIMUM_OPACITY_ALLOWED_FOR_S_AND_HIGHER = 0.8f;
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({AUTOPLAY_TYPE_ALWAYS, AUTOPLAY_TYPE_WIFI,
|
||||
AUTOPLAY_TYPE_NEVER})
|
||||
@ -525,90 +504,10 @@ public final class PlayerHelper {
|
||||
.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param playerUi {@code screenWidth} and {@code screenHeight} must have been initialized
|
||||
* @return the popup starting layout params
|
||||
*/
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public static WindowManager.LayoutParams retrievePopupLayoutParamsFromPrefs(
|
||||
final PopupPlayerUi playerUi) {
|
||||
final SharedPreferences prefs = playerUi.getPlayer().getPrefs();
|
||||
final Context context = playerUi.getPlayer().getContext();
|
||||
|
||||
final boolean popupRememberSizeAndPos = prefs.getBoolean(
|
||||
context.getString(R.string.popup_remember_size_pos_key), true);
|
||||
final float defaultSize = context.getResources().getDimension(R.dimen.popup_default_width);
|
||||
final float popupWidth = popupRememberSizeAndPos
|
||||
? prefs.getFloat(context.getString(R.string.popup_saved_width_key), defaultSize)
|
||||
: defaultSize;
|
||||
final float popupHeight = getMinimumVideoHeight(popupWidth);
|
||||
|
||||
final WindowManager.LayoutParams popupLayoutParams = new WindowManager.LayoutParams(
|
||||
(int) popupWidth, (int) popupHeight,
|
||||
popupLayoutParamType(),
|
||||
IDLE_WINDOW_FLAGS,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
popupLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
|
||||
popupLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
|
||||
final int centerX = (int) (playerUi.getScreenWidth() / 2f - popupWidth / 2f);
|
||||
final int centerY = (int) (playerUi.getScreenHeight() / 2f - popupHeight / 2f);
|
||||
popupLayoutParams.x = popupRememberSizeAndPos
|
||||
? prefs.getInt(context.getString(R.string.popup_saved_x_key), centerX) : centerX;
|
||||
popupLayoutParams.y = popupRememberSizeAndPos
|
||||
? prefs.getInt(context.getString(R.string.popup_saved_y_key), centerY) : centerY;
|
||||
|
||||
return popupLayoutParams;
|
||||
}
|
||||
|
||||
public static void savePopupPositionAndSizeToPrefs(final PopupPlayerUi playerUi) {
|
||||
if (playerUi.getPopupLayoutParams() != null) {
|
||||
final Context context = playerUi.getPlayer().getContext();
|
||||
playerUi.getPlayer().getPrefs().edit()
|
||||
.putFloat(context.getString(R.string.popup_saved_width_key),
|
||||
playerUi.getPopupLayoutParams().width)
|
||||
.putInt(context.getString(R.string.popup_saved_x_key),
|
||||
playerUi.getPopupLayoutParams().x)
|
||||
.putInt(context.getString(R.string.popup_saved_y_key),
|
||||
playerUi.getPopupLayoutParams().y)
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
||||
public static float getMinimumVideoHeight(final float width) {
|
||||
return width / (16.0f / 9.0f); // Respect the 16:9 ratio that most videos have
|
||||
}
|
||||
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public static WindowManager.LayoutParams buildCloseOverlayLayoutParams() {
|
||||
final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|
||||
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||
|
||||
final WindowManager.LayoutParams closeOverlayLayoutParams = new WindowManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
popupLayoutParamType(),
|
||||
flags,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
// Setting maximum opacity allowed for touch events to other apps for Android 12 and
|
||||
// higher to prevent non interaction when using other apps with the popup player
|
||||
closeOverlayLayoutParams.alpha = MAXIMUM_OPACITY_ALLOWED_FOR_S_AND_HIGHER;
|
||||
}
|
||||
|
||||
closeOverlayLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
|
||||
closeOverlayLayoutParams.softInputMode =
|
||||
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
return closeOverlayLayoutParams;
|
||||
}
|
||||
|
||||
public static int popupLayoutParamType() {
|
||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
||||
? WindowManager.LayoutParams.TYPE_PHONE
|
||||
: WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
}
|
||||
|
||||
public static int retrieveSeekDurationFromPreferences(final Player player) {
|
||||
return Integer.parseInt(Objects.requireNonNull(player.getPrefs().getString(
|
||||
player.getContext().getString(R.string.seek_duration_key),
|
||||
|
@ -2,21 +2,25 @@ package org.schabi.newpipe.player.ui;
|
||||
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static org.schabi.newpipe.MainActivity.DEBUG;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.buildCloseOverlayLayoutParams;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.getMinimumVideoHeight;
|
||||
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePopupLayoutParamsFromPrefs;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Build;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.AnticipateInterpolator;
|
||||
import android.widget.LinearLayout;
|
||||
@ -38,6 +42,20 @@ import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
public final class PopupPlayerUi extends VideoPlayerUi {
|
||||
private static final String TAG = PopupPlayerUi.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Maximum opacity allowed for Android 12 and higher to allow touches on other apps when using
|
||||
* NewPipe's popup player.
|
||||
*
|
||||
* <p>
|
||||
* This value is hardcoded instead of being get dynamically with the method linked of the
|
||||
* constant documentation below, because it is not static and popup player layout parameters
|
||||
* are generated with static methods.
|
||||
* </p>
|
||||
*
|
||||
* @see WindowManager.LayoutParams#FLAG_NOT_TOUCHABLE
|
||||
*/
|
||||
private static final float MAXIMUM_OPACITY_ALLOWED_FOR_S_AND_HIGHER = 0.8f;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Popup player
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@ -98,7 +116,7 @@ public final class PopupPlayerUi extends VideoPlayerUi {
|
||||
|
||||
updateScreenSize();
|
||||
|
||||
popupLayoutParams = retrievePopupLayoutParamsFromPrefs(this);
|
||||
popupLayoutParams = retrievePopupLayoutParamsFromPrefs();
|
||||
binding.surfaceView.setHeights(popupLayoutParams.height, popupLayoutParams.height);
|
||||
|
||||
checkPopupPositionBounds();
|
||||
@ -446,6 +464,92 @@ public final class PopupPlayerUi extends VideoPlayerUi {
|
||||
//endregion
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Popup & closing overlay layout params + saving popup position and size
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
//region Popup & closing overlay layout params + saving popup position and size
|
||||
|
||||
/**
|
||||
* {@code screenWidth} and {@code screenHeight} must have been initialized.
|
||||
* @return the popup starting layout params
|
||||
*/
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public WindowManager.LayoutParams retrievePopupLayoutParamsFromPrefs() {
|
||||
final SharedPreferences prefs = getPlayer().getPrefs();
|
||||
final Context context = getPlayer().getContext();
|
||||
|
||||
final boolean popupRememberSizeAndPos = prefs.getBoolean(
|
||||
context.getString(R.string.popup_remember_size_pos_key), true);
|
||||
final float defaultSize = context.getResources().getDimension(R.dimen.popup_default_width);
|
||||
final float popupWidth = popupRememberSizeAndPos
|
||||
? prefs.getFloat(context.getString(R.string.popup_saved_width_key), defaultSize)
|
||||
: defaultSize;
|
||||
final float popupHeight = getMinimumVideoHeight(popupWidth);
|
||||
|
||||
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
|
||||
(int) popupWidth, (int) popupHeight,
|
||||
popupLayoutParamType(),
|
||||
IDLE_WINDOW_FLAGS,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
params.gravity = Gravity.LEFT | Gravity.TOP;
|
||||
params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
|
||||
final int centerX = (int) (screenWidth / 2f - popupWidth / 2f);
|
||||
final int centerY = (int) (screenHeight / 2f - popupHeight / 2f);
|
||||
params.x = popupRememberSizeAndPos
|
||||
? prefs.getInt(context.getString(R.string.popup_saved_x_key), centerX) : centerX;
|
||||
params.y = popupRememberSizeAndPos
|
||||
? prefs.getInt(context.getString(R.string.popup_saved_y_key), centerY) : centerY;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
public void savePopupPositionAndSizeToPrefs() {
|
||||
if (getPopupLayoutParams() != null) {
|
||||
final Context context = getPlayer().getContext();
|
||||
getPlayer().getPrefs().edit()
|
||||
.putFloat(context.getString(R.string.popup_saved_width_key),
|
||||
popupLayoutParams.width)
|
||||
.putInt(context.getString(R.string.popup_saved_x_key),
|
||||
popupLayoutParams.x)
|
||||
.putInt(context.getString(R.string.popup_saved_y_key),
|
||||
popupLayoutParams.y)
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("RtlHardcoded")
|
||||
public static WindowManager.LayoutParams buildCloseOverlayLayoutParams() {
|
||||
final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|
||||
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||
|
||||
final WindowManager.LayoutParams closeOverlayLayoutParams = new WindowManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
popupLayoutParamType(),
|
||||
flags,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
// Setting maximum opacity allowed for touch events to other apps for Android 12 and
|
||||
// higher to prevent non interaction when using other apps with the popup player
|
||||
closeOverlayLayoutParams.alpha = MAXIMUM_OPACITY_ALLOWED_FOR_S_AND_HIGHER;
|
||||
}
|
||||
|
||||
closeOverlayLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
|
||||
closeOverlayLayoutParams.softInputMode =
|
||||
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
return closeOverlayLayoutParams;
|
||||
}
|
||||
|
||||
public static int popupLayoutParamType() {
|
||||
return Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
||||
? WindowManager.LayoutParams.TYPE_PHONE
|
||||
: WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
}
|
||||
//endregion
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
Loading…
Reference in New Issue
Block a user