@byteplus/react-native-live-pull 1.1.3-rc.4 → 1.1.4-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/volcengine/velive/rn/pull/pictureInpicture/FloatingWindowService.java +40 -719
- package/lib/commonjs/index.js +8 -65
- package/lib/module/index.js +9 -66
- package/lib/typescript/codegen/ios/api.d.ts +0 -1
- package/package.json +1 -1
- package/react-native-velive-pull.podspec +1 -1
- package/lib/typescript/core/appState.d.ts +0 -3
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package com.volcengine.velive.rn.pull.pictureInpicture;
|
|
2
2
|
|
|
3
|
-
import android.animation.ValueAnimator;
|
|
4
3
|
import android.app.Service;
|
|
5
4
|
import android.content.BroadcastReceiver;
|
|
6
5
|
import android.content.Context;
|
|
@@ -25,19 +24,14 @@ import androidx.annotation.Nullable;
|
|
|
25
24
|
import com.volcengine.velive.rn.pull.R;
|
|
26
25
|
|
|
27
26
|
public class FloatingWindowService extends Service {
|
|
28
|
-
private static final int MARGIN_TOP = 40;
|
|
29
|
-
private static final int MARGIN_BOTTOM = 40;
|
|
30
|
-
private static final int MARGIN_LEFT = 20;
|
|
31
|
-
private static final int MARGIN_RIGHT = 20;
|
|
32
27
|
private static final String TAG = FloatingWindowService.class.getSimpleName();
|
|
28
|
+
private static final int LONGER_SIDE_MAX_LEN = 1000;
|
|
33
29
|
|
|
34
30
|
private WindowManager mWindowManager;
|
|
35
31
|
private WindowManager.LayoutParams mLayoutParams;
|
|
36
32
|
private SurfaceView mSurfaceView;
|
|
37
33
|
private View mSmallWindowView;
|
|
38
34
|
private ActivityLaunchReceiver mActivityLaunchReceiver;
|
|
39
|
-
private FloatingOnTouchListener
|
|
40
|
-
mFloatingOnTouchListener; // Store the listener instance
|
|
41
35
|
|
|
42
36
|
public static final String ACTION_STOP_PIP_SERVICE =
|
|
43
37
|
"com.volcengine.velive.rn.pull.STOP_PIP_SERVICE";
|
|
@@ -103,68 +97,37 @@ public class FloatingWindowService extends Service {
|
|
|
103
97
|
int screenWidth = displayMetrics.widthPixels;
|
|
104
98
|
int screenHeight = displayMetrics.heightPixels;
|
|
105
99
|
|
|
106
|
-
|
|
107
|
-
int
|
|
100
|
+
// Calculate the minimum screen dimension
|
|
101
|
+
int minScreenDim = Math.min(screenWidth, screenHeight);
|
|
108
102
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
int maxLen;
|
|
112
|
-
if (isPortrait) {
|
|
113
|
-
// 竖屏时,宽度不能超过 drawableWidth
|
|
114
|
-
maxLen = drawableWidth;
|
|
115
|
-
} else {
|
|
116
|
-
// 横屏时,高度不能超过 drawableHeight
|
|
117
|
-
maxLen = drawableHeight;
|
|
118
|
-
}
|
|
103
|
+
// Determine the maximum length based on the smaller of 1000 and
|
|
104
|
+
// minScreenDim
|
|
105
|
+
int maxLen = Math.min(LONGER_SIDE_MAX_LEN, minScreenDim);
|
|
119
106
|
|
|
107
|
+
// Limit the floating window size to prevent it from being too large or too
|
|
108
|
+
// small, control the longer side to maxLen, scale the shorter
|
|
109
|
+
// side proportionally
|
|
120
110
|
int width, height;
|
|
121
|
-
if (aspectRatio >= 1) {
|
|
111
|
+
if (aspectRatio >= 1) {
|
|
112
|
+
height = (int)(maxLen / aspectRatio);
|
|
122
113
|
width = maxLen;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
width = drawableWidth;
|
|
126
|
-
height = (int)(width / aspectRatio);
|
|
127
|
-
}
|
|
128
|
-
if (!isPortrait &&
|
|
129
|
-
height > drawableHeight) { // 横屏下,若计算出的高度超出drawableHeight
|
|
130
|
-
height = drawableHeight;
|
|
131
|
-
width = (int)(height * aspectRatio);
|
|
132
|
-
}
|
|
133
|
-
} else { // 高大于宽 (竖向视频)
|
|
114
|
+
} else {
|
|
115
|
+
width = (int)(maxLen * aspectRatio);
|
|
134
116
|
height = maxLen;
|
|
135
|
-
width = (int)(height * aspectRatio);
|
|
136
|
-
if (!isPortrait && height > drawableHeight) {
|
|
137
|
-
height = drawableHeight;
|
|
138
|
-
width = (int)(height * aspectRatio);
|
|
139
|
-
}
|
|
140
|
-
if (isPortrait &&
|
|
141
|
-
width > drawableWidth) { // 竖屏下,若计算出的宽度超出drawableWidth
|
|
142
|
-
width = drawableWidth;
|
|
143
|
-
height = (int)(width / aspectRatio);
|
|
144
|
-
}
|
|
145
117
|
}
|
|
118
|
+
mLayoutParams.width = width;
|
|
119
|
+
mLayoutParams.height = height;
|
|
146
120
|
|
|
147
|
-
//
|
|
148
|
-
mLayoutParams.
|
|
149
|
-
mLayoutParams.
|
|
150
|
-
|
|
151
|
-
// Initial position of the floating window, respecting margins
|
|
152
|
-
mLayoutParams.x =
|
|
153
|
-
Math.max(MARGIN_LEFT,
|
|
154
|
-
Math.min(x, screenWidth - mLayoutParams.width - MARGIN_RIGHT));
|
|
155
|
-
mLayoutParams.y =
|
|
156
|
-
Math.max(MARGIN_TOP, Math.min(y, screenHeight - mLayoutParams.height -
|
|
157
|
-
MARGIN_BOTTOM));
|
|
121
|
+
// Initial position of the floating window
|
|
122
|
+
mLayoutParams.x = x;
|
|
123
|
+
mLayoutParams.y = y;
|
|
158
124
|
|
|
159
125
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
160
126
|
if (Settings.canDrawOverlays(this)) {
|
|
161
127
|
LayoutInflater layoutInflater = LayoutInflater.from(this);
|
|
162
128
|
mSmallWindowView =
|
|
163
129
|
layoutInflater.inflate(R.layout.floating_window_layout, null);
|
|
164
|
-
|
|
165
|
-
new FloatingOnTouchListener(); // Create and store the instance
|
|
166
|
-
mSmallWindowView.setOnTouchListener(
|
|
167
|
-
this.mFloatingOnTouchListener); // Set the stored instance
|
|
130
|
+
mSmallWindowView.setOnTouchListener(new FloatingOnTouchListener());
|
|
168
131
|
mWindowManager.addView(mSmallWindowView, mLayoutParams);
|
|
169
132
|
mSurfaceView = mSmallWindowView.findViewById(R.id.surface_view);
|
|
170
133
|
mSmallWindowView.findViewById(R.id.surface_close_btn)
|
|
@@ -241,8 +204,6 @@ public class FloatingWindowService extends Service {
|
|
|
241
204
|
}
|
|
242
205
|
|
|
243
206
|
private class FloatingOnTouchListener implements View.OnTouchListener {
|
|
244
|
-
private boolean isDoubleClickAnimating =
|
|
245
|
-
false; // Flag to indicate if double-click animation is running
|
|
246
207
|
private final int touchSlop =
|
|
247
208
|
ViewConfiguration
|
|
248
209
|
.get(FloatingWindowService.this.getApplicationContext())
|
|
@@ -251,289 +212,36 @@ public class FloatingWindowService extends Service {
|
|
|
251
212
|
private int x, y;
|
|
252
213
|
private boolean isDragging;
|
|
253
214
|
|
|
254
|
-
private static final int MODE_NONE = 0;
|
|
255
|
-
private static final int MODE_DRAG = 1;
|
|
256
|
-
private static final int MODE_ZOOM = 2;
|
|
257
|
-
private int mode = MODE_NONE;
|
|
258
|
-
|
|
259
|
-
private float oldDist = 1f;
|
|
260
|
-
private float initialAspectRatio;
|
|
261
|
-
private int initialWidth;
|
|
262
|
-
private int initialHeight;
|
|
263
|
-
|
|
264
|
-
// Screen metrics
|
|
265
|
-
private DisplayMetrics displayMetrics = new DisplayMetrics();
|
|
266
|
-
private int screenWidth;
|
|
267
|
-
private int screenHeight;
|
|
268
|
-
private int drawableWidth;
|
|
269
|
-
private int drawableHeight;
|
|
270
|
-
private boolean isPortraitScreen;
|
|
271
|
-
|
|
272
|
-
private long lastClickTime = 0;
|
|
273
|
-
private static final long DOUBLE_CLICK_TIME_DELTA = 200; // milliseconds
|
|
274
|
-
|
|
275
|
-
private final float ZOOM_SCALE_FACTOR =
|
|
276
|
-
1.5f; // Factor to zoom in/out on double tap
|
|
277
|
-
|
|
278
|
-
private void updateScreenMetrics() {
|
|
279
|
-
mWindowManager.getDefaultDisplay().getMetrics(displayMetrics);
|
|
280
|
-
screenWidth = displayMetrics.widthPixels;
|
|
281
|
-
screenHeight = displayMetrics.heightPixels;
|
|
282
|
-
drawableWidth = screenWidth - MARGIN_LEFT - MARGIN_RIGHT;
|
|
283
|
-
drawableHeight = screenHeight - MARGIN_TOP - MARGIN_BOTTOM;
|
|
284
|
-
isPortraitScreen = screenHeight > screenWidth;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
215
|
@Override
|
|
288
216
|
public boolean onTouch(View view, MotionEvent event) {
|
|
289
|
-
|
|
290
|
-
// as orientation or screen size might have changed since last touch.
|
|
291
|
-
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
|
292
|
-
updateScreenMetrics();
|
|
293
|
-
}
|
|
294
|
-
// If currently animating from double click, consume touch events to
|
|
295
|
-
// prevent interference
|
|
296
|
-
if (isDoubleClickAnimating) {
|
|
297
|
-
// Allow ACTION_UP to potentially clear the flag if animation ends early
|
|
298
|
-
// or is cancelled but primarily, prevent new gestures from starting.
|
|
299
|
-
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
|
300
|
-
mode = MODE_NONE; // Prevent drag/zoom from starting
|
|
301
|
-
}
|
|
302
|
-
return true; // Consume the event
|
|
303
|
-
}
|
|
304
|
-
switch (event.getAction() & MotionEvent.ACTION_MASK) {
|
|
305
|
-
case MotionEvent.ACTION_DOWN:
|
|
306
|
-
downX = x = (int)event.getRawX();
|
|
307
|
-
downY = y = (int)event.getRawY();
|
|
308
|
-
mode = MODE_DRAG;
|
|
309
|
-
initialAspectRatio = (float)mLayoutParams.width / mLayoutParams.height;
|
|
310
|
-
initialWidth = mLayoutParams.width;
|
|
311
|
-
initialHeight = mLayoutParams.height;
|
|
312
|
-
|
|
313
|
-
// Double tap detection
|
|
314
|
-
long clickTime = System.currentTimeMillis();
|
|
315
|
-
if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA) {
|
|
316
|
-
handleDoubleClick(view);
|
|
317
|
-
}
|
|
318
|
-
lastClickTime = clickTime;
|
|
319
|
-
break;
|
|
320
|
-
case MotionEvent.ACTION_POINTER_DOWN:
|
|
321
|
-
oldDist = spacing(event);
|
|
322
|
-
if (oldDist > 10f) {
|
|
323
|
-
mode = MODE_ZOOM;
|
|
324
|
-
}
|
|
325
|
-
break;
|
|
217
|
+
switch (event.getAction()) {
|
|
326
218
|
case MotionEvent.ACTION_UP:
|
|
327
|
-
case MotionEvent.ACTION_POINTER_UP:
|
|
328
|
-
boolean wasZooming = (mode == MODE_ZOOM);
|
|
329
|
-
// Capture params before mode is reset
|
|
330
|
-
int xBeforeSnap = mLayoutParams.x;
|
|
331
|
-
int widthBeforeSnap = mLayoutParams.width;
|
|
332
|
-
|
|
333
|
-
mode = MODE_NONE; // Reset mode
|
|
334
|
-
|
|
335
219
|
if (isDragging) {
|
|
336
220
|
isDragging = false;
|
|
337
|
-
// Perform snap animation if it was a drag or end of zoom
|
|
338
|
-
if (event.getPointerCount() == 1 || wasZooming) {
|
|
339
|
-
Log.i(TAG, "ACTION_UP/POINTER_UP: Triggering snap. xBeforeSnap=" +
|
|
340
|
-
xBeforeSnap + ", widthBeforeSnap=" +
|
|
341
|
-
widthBeforeSnap + ", wasZooming=" + wasZooming +
|
|
342
|
-
", pointerCount=" + event.getPointerCount());
|
|
343
|
-
animateSnapToEdge(view);
|
|
344
|
-
}
|
|
345
221
|
} else {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
(event.getAction() & MotionEvent.ACTION_MASK) ==
|
|
349
|
-
MotionEvent.ACTION_UP) {
|
|
350
|
-
// Check if it was a drag or a tap
|
|
351
|
-
if (Math.abs(event.getRawX() - downX) < touchSlop &&
|
|
352
|
-
Math.abs(event.getRawY() - downY) < touchSlop) {
|
|
353
|
-
// This is a tap, not a double tap, so handle as single click if
|
|
354
|
-
// needed For now, double tap handles zoom, single tap is handled
|
|
355
|
-
// by new_window_btn
|
|
356
|
-
}
|
|
357
|
-
}
|
|
222
|
+
FloatingWindowHelper.getInstance().onClickFloatingWindow(
|
|
223
|
+
FloatingWindowService.this);
|
|
358
224
|
}
|
|
359
|
-
|
|
225
|
+
downX = downY = 0;
|
|
226
|
+
break;
|
|
227
|
+
case MotionEvent.ACTION_DOWN:
|
|
228
|
+
downX = x = (int)event.getRawX();
|
|
229
|
+
downY = y = (int)event.getRawY();
|
|
360
230
|
break;
|
|
361
|
-
|
|
362
231
|
case MotionEvent.ACTION_MOVE:
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
// 使用预先获取的屏幕高度 screenHeight
|
|
377
|
-
// 限制y坐标在安全区域内
|
|
378
|
-
mLayoutParams.y = Math.max(
|
|
379
|
-
MARGIN_TOP, Math.min(mLayoutParams.y, this.screenHeight -
|
|
380
|
-
mLayoutParams.height -
|
|
381
|
-
MARGIN_BOTTOM));
|
|
382
|
-
|
|
383
|
-
mWindowManager.updateViewLayout(view, mLayoutParams);
|
|
384
|
-
}
|
|
385
|
-
x = nowX;
|
|
386
|
-
y = nowY;
|
|
387
|
-
} else if (mode == MODE_ZOOM && event.getPointerCount() >= 2) {
|
|
388
|
-
float newDist = spacing(event);
|
|
389
|
-
if (newDist > 10f) {
|
|
390
|
-
// Calculate midpoint of the two fingers
|
|
391
|
-
float midX = (event.getX(0) + event.getX(1)) / 2;
|
|
392
|
-
float midY = (event.getY(0) + event.getY(1)) / 2;
|
|
393
|
-
|
|
394
|
-
// Convert midpoint from view coordinates to screen coordinates
|
|
395
|
-
float screenMidX = mLayoutParams.x + midX;
|
|
396
|
-
float screenMidY = mLayoutParams.y + midY;
|
|
397
|
-
|
|
398
|
-
float scale = newDist / oldDist;
|
|
399
|
-
int oldWidth = mLayoutParams.width;
|
|
400
|
-
int oldHeight = mLayoutParams.height;
|
|
401
|
-
int newWidth = (int)(oldWidth * scale);
|
|
402
|
-
int newHeight = (int)(oldHeight * scale);
|
|
403
|
-
|
|
404
|
-
// Use pre-calculated screen metrics
|
|
405
|
-
// Screen metrics are now updated in onTouch ACTION_DOWN, so they
|
|
406
|
-
// should be current here.
|
|
407
|
-
|
|
408
|
-
// Min size constraints: 1/2 of initial size, but not smaller than a
|
|
409
|
-
// fraction of screen respecting margins
|
|
410
|
-
int minAllowedWidth;
|
|
411
|
-
int minAllowedHeight;
|
|
412
|
-
if (isPortraitScreen) {
|
|
413
|
-
minAllowedWidth = Math.max(initialWidth / 2, drawableWidth / 2);
|
|
414
|
-
minAllowedHeight = (int)(minAllowedWidth / initialAspectRatio);
|
|
415
|
-
} else {
|
|
416
|
-
minAllowedHeight =
|
|
417
|
-
Math.max(initialHeight / 2, drawableHeight / 2);
|
|
418
|
-
minAllowedWidth = (int)(minAllowedHeight * initialAspectRatio);
|
|
419
|
-
}
|
|
420
|
-
// Ensure min dimensions are at least 1
|
|
421
|
-
minAllowedWidth = Math.max(1, minAllowedWidth);
|
|
422
|
-
minAllowedHeight = Math.max(1, minAllowedHeight);
|
|
423
|
-
|
|
424
|
-
// Max size constraints based on orientation and margins
|
|
425
|
-
int maxAllowedWidth, maxAllowedHeight;
|
|
426
|
-
if (isPortraitScreen) {
|
|
427
|
-
maxAllowedWidth = drawableWidth;
|
|
428
|
-
maxAllowedHeight =
|
|
429
|
-
(int)(maxAllowedWidth /
|
|
430
|
-
initialAspectRatio); // Maintain aspect ratio
|
|
431
|
-
if (maxAllowedHeight >
|
|
432
|
-
drawableHeight) { // If calculated height is too much for
|
|
433
|
-
// portrait
|
|
434
|
-
maxAllowedHeight = drawableHeight;
|
|
435
|
-
maxAllowedWidth = (int)(maxAllowedHeight * initialAspectRatio);
|
|
436
|
-
}
|
|
437
|
-
} else { // Landscape screen
|
|
438
|
-
maxAllowedHeight = drawableHeight;
|
|
439
|
-
maxAllowedWidth =
|
|
440
|
-
(int)(maxAllowedHeight *
|
|
441
|
-
initialAspectRatio); // Maintain aspect ratio
|
|
442
|
-
if (maxAllowedWidth > drawableWidth) { // If calculated width is
|
|
443
|
-
// too much for landscape
|
|
444
|
-
maxAllowedWidth = drawableWidth;
|
|
445
|
-
maxAllowedHeight = (int)(maxAllowedWidth / initialAspectRatio);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
// maxAllowedWidth = Math.min(maxAllowedWidth, LONGER_SIDE_MAX_LEN);
|
|
449
|
-
// // Global max len - Removed maxAllowedHeight =
|
|
450
|
-
// Math.min(maxAllowedHeight, LONGER_SIDE_MAX_LEN); // Global max
|
|
451
|
-
// len - Removed
|
|
452
|
-
if (initialAspectRatio >= 1)
|
|
453
|
-
maxAllowedHeight = (int)(maxAllowedWidth / initialAspectRatio);
|
|
454
|
-
else
|
|
455
|
-
maxAllowedWidth = (int)(maxAllowedHeight * initialAspectRatio);
|
|
456
|
-
|
|
457
|
-
// Apply scaling
|
|
458
|
-
newWidth = (int)(oldWidth * scale);
|
|
459
|
-
newHeight = (int)(oldHeight * scale);
|
|
460
|
-
|
|
461
|
-
// Clamp to min/max size while maintaining aspect ratio
|
|
462
|
-
if (scale < 1) { // Shrinking
|
|
463
|
-
newWidth = Math.max(minAllowedWidth, newWidth);
|
|
464
|
-
newHeight = (int)(newWidth / initialAspectRatio);
|
|
465
|
-
if (newHeight < minAllowedHeight) {
|
|
466
|
-
newHeight = minAllowedHeight;
|
|
467
|
-
newWidth = (int)(newHeight * initialAspectRatio);
|
|
468
|
-
}
|
|
469
|
-
} else { // Expanding
|
|
470
|
-
newWidth = Math.min(maxAllowedWidth, newWidth);
|
|
471
|
-
newHeight = (int)(newWidth / initialAspectRatio);
|
|
472
|
-
if (newHeight > maxAllowedHeight) {
|
|
473
|
-
newHeight = maxAllowedHeight;
|
|
474
|
-
newWidth = (int)(newHeight * initialAspectRatio);
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Final check to ensure dimensions are within absolute min/max
|
|
479
|
-
// bounds
|
|
480
|
-
newWidth =
|
|
481
|
-
Math.max(minAllowedWidth, Math.min(newWidth, maxAllowedWidth));
|
|
482
|
-
newHeight =
|
|
483
|
-
(int)(newWidth / initialAspectRatio); // Maintain aspect ratio
|
|
484
|
-
// Ensure height is also clamped correctly after width adjustment
|
|
485
|
-
if (newHeight < minAllowedHeight) {
|
|
486
|
-
newHeight = minAllowedHeight;
|
|
487
|
-
newWidth = (int)(newHeight * initialAspectRatio);
|
|
488
|
-
}
|
|
489
|
-
if (newHeight > maxAllowedHeight) {
|
|
490
|
-
newHeight = maxAllowedHeight;
|
|
491
|
-
newWidth = (int)(newHeight * initialAspectRatio);
|
|
492
|
-
}
|
|
493
|
-
// Re-clamp width just in case height clamping affected it and
|
|
494
|
-
// pushed it out of width bounds
|
|
495
|
-
newWidth =
|
|
496
|
-
Math.max(minAllowedWidth, Math.min(newWidth, maxAllowedWidth));
|
|
497
|
-
|
|
498
|
-
// Adjust position to keep the zoom centered on the midpoint
|
|
499
|
-
mLayoutParams.x = (int)(screenMidX - (midX * newWidth / oldWidth));
|
|
500
|
-
mLayoutParams.y =
|
|
501
|
-
(int)(screenMidY - (midY * newHeight / oldHeight));
|
|
502
|
-
|
|
503
|
-
mLayoutParams.width = newWidth;
|
|
504
|
-
mLayoutParams.height = newHeight;
|
|
505
|
-
|
|
506
|
-
// Prevent window from going off-screen after repositioning
|
|
507
|
-
// For Y, keep margin constraints
|
|
508
|
-
mLayoutParams.y = Math.max(
|
|
509
|
-
MARGIN_TOP,
|
|
510
|
-
Math.min(mLayoutParams.y,
|
|
511
|
-
screenHeight - mLayoutParams.height - MARGIN_BOTTOM));
|
|
512
|
-
// For X, constrain to screen physical edges only during zoom,
|
|
513
|
-
// let animateSnapToEdge handle final margin snapping.
|
|
514
|
-
mLayoutParams.x = Math.max(
|
|
515
|
-
0, // Screen physical left edge
|
|
516
|
-
Math.min(
|
|
517
|
-
mLayoutParams.x,
|
|
518
|
-
screenWidth -
|
|
519
|
-
mLayoutParams.width)); // Screen physical right edge
|
|
520
|
-
|
|
521
|
-
// 更新SurfaceView的布局参数
|
|
522
|
-
if (mSurfaceView != null) {
|
|
523
|
-
android.view.ViewGroup.LayoutParams surfaceParams =
|
|
524
|
-
mSurfaceView.getLayoutParams();
|
|
525
|
-
if (surfaceParams != null) {
|
|
526
|
-
surfaceParams.width = mLayoutParams.width;
|
|
527
|
-
surfaceParams.height = mLayoutParams.height;
|
|
528
|
-
mSurfaceView.setLayoutParams(surfaceParams);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
mWindowManager.updateViewLayout(view, mLayoutParams);
|
|
532
|
-
oldDist = newDist;
|
|
533
|
-
}
|
|
534
|
-
isDragging =
|
|
535
|
-
true; // Zooming implies dragging state for click handling
|
|
536
|
-
}
|
|
232
|
+
int nowX = (int)event.getRawX();
|
|
233
|
+
int nowY = (int)event.getRawY();
|
|
234
|
+
if (Math.abs(nowX - downX) > touchSlop ||
|
|
235
|
+
Math.abs(nowY - downY) > touchSlop) {
|
|
236
|
+
isDragging = true;
|
|
237
|
+
}
|
|
238
|
+
int movedX = nowX - x;
|
|
239
|
+
int movedY = nowY - y;
|
|
240
|
+
x = nowX;
|
|
241
|
+
y = nowY;
|
|
242
|
+
mLayoutParams.x = mLayoutParams.x + movedX;
|
|
243
|
+
mLayoutParams.y = mLayoutParams.y + movedY;
|
|
244
|
+
mWindowManager.updateViewLayout(view, mLayoutParams);
|
|
537
245
|
break;
|
|
538
246
|
|
|
539
247
|
default:
|
|
@@ -541,392 +249,5 @@ public class FloatingWindowService extends Service {
|
|
|
541
249
|
}
|
|
542
250
|
return true;
|
|
543
251
|
}
|
|
544
|
-
|
|
545
|
-
private float spacing(MotionEvent event) {
|
|
546
|
-
if (event.getPointerCount() < 2)
|
|
547
|
-
return 0f;
|
|
548
|
-
float x = event.getX(0) - event.getX(1);
|
|
549
|
-
float y = event.getY(0) - event.getY(1);
|
|
550
|
-
return (float)Math.sqrt(x * x + y * y);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
private void handleDoubleClick(View view) {
|
|
554
|
-
Log.d(TAG, "Double tap detected");
|
|
555
|
-
int targetWidth, targetHeight;
|
|
556
|
-
|
|
557
|
-
// Use pre-calculated screen metrics
|
|
558
|
-
// updateScreenMetrics(); // Ensure metrics are fresh if not updated in
|
|
559
|
-
// onTouch ACTION_DOWN Screen metrics are now updated in onTouch
|
|
560
|
-
// ACTION_DOWN, so they should be current here.
|
|
561
|
-
|
|
562
|
-
// Minimum size: 1/2 of initial size, but not smaller than a fraction of
|
|
563
|
-
// screen respecting margins
|
|
564
|
-
int minAllowedWidth = initialWidth / 2;
|
|
565
|
-
int minAllowedHeight = initialHeight / 2;
|
|
566
|
-
if (isPortraitScreen) {
|
|
567
|
-
minAllowedWidth = Math.max(minAllowedWidth, drawableWidth / 2);
|
|
568
|
-
minAllowedHeight = (int)(minAllowedWidth / initialAspectRatio);
|
|
569
|
-
} else {
|
|
570
|
-
minAllowedHeight = Math.max(minAllowedHeight, drawableHeight / 2);
|
|
571
|
-
minAllowedWidth = (int)(minAllowedHeight * initialAspectRatio);
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// Maximum size based on orientation and margins
|
|
575
|
-
int maxAllowedTargetWidth, maxAllowedTargetHeight;
|
|
576
|
-
if (isPortraitScreen) {
|
|
577
|
-
maxAllowedTargetWidth = drawableWidth;
|
|
578
|
-
maxAllowedTargetHeight =
|
|
579
|
-
(int)(maxAllowedTargetWidth / initialAspectRatio);
|
|
580
|
-
if (maxAllowedTargetHeight > drawableHeight) {
|
|
581
|
-
maxAllowedTargetHeight = drawableHeight;
|
|
582
|
-
maxAllowedTargetWidth =
|
|
583
|
-
(int)(maxAllowedTargetHeight * initialAspectRatio);
|
|
584
|
-
}
|
|
585
|
-
} else { // Landscape screen
|
|
586
|
-
maxAllowedTargetHeight = drawableHeight;
|
|
587
|
-
maxAllowedTargetWidth =
|
|
588
|
-
(int)(maxAllowedTargetHeight * initialAspectRatio);
|
|
589
|
-
if (maxAllowedTargetWidth > drawableWidth) {
|
|
590
|
-
maxAllowedTargetWidth = drawableWidth;
|
|
591
|
-
maxAllowedTargetHeight =
|
|
592
|
-
(int)(maxAllowedTargetWidth / initialAspectRatio);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
// Apply global LONGER_SIDE_MAX_LEN constraint - Removed
|
|
596
|
-
// if (initialAspectRatio >= 1) { // Landscape or square video
|
|
597
|
-
// maxAllowedTargetWidth =
|
|
598
|
-
// Math.min(maxAllowedTargetWidth, LONGER_SIDE_MAX_LEN);
|
|
599
|
-
// maxAllowedTargetHeight =
|
|
600
|
-
// (int)(maxAllowedTargetWidth / initialAspectRatio);
|
|
601
|
-
// } else { // Portrait video
|
|
602
|
-
// maxAllowedTargetHeight =
|
|
603
|
-
// Math.min(maxAllowedTargetHeight, LONGER_SIDE_MAX_LEN);
|
|
604
|
-
// maxAllowedTargetWidth =
|
|
605
|
-
// (int)(maxAllowedTargetHeight * initialAspectRatio);
|
|
606
|
-
// }
|
|
607
|
-
|
|
608
|
-
int currentX = mLayoutParams.x;
|
|
609
|
-
int currentY = mLayoutParams.y;
|
|
610
|
-
int currentWidth = mLayoutParams.width;
|
|
611
|
-
int currentHeight = mLayoutParams.height;
|
|
612
|
-
|
|
613
|
-
int finalTargetX = currentX;
|
|
614
|
-
int finalTargetY = currentY;
|
|
615
|
-
|
|
616
|
-
// 计算当前宽度与中间值的比较,决定缩放方向
|
|
617
|
-
int midWidth = (minAllowedWidth + maxAllowedTargetWidth) / 2;
|
|
618
|
-
if (currentWidth < midWidth) {
|
|
619
|
-
// 当前更接近最小值,放大到最大尺寸
|
|
620
|
-
targetWidth = maxAllowedTargetWidth;
|
|
621
|
-
targetHeight = maxAllowedTargetHeight;
|
|
622
|
-
Log.d(TAG, "Zooming in to max: " + targetWidth + "x" + targetHeight);
|
|
623
|
-
} else {
|
|
624
|
-
// 当前更接近最大值,缩小到最小尺寸
|
|
625
|
-
targetWidth = minAllowedWidth;
|
|
626
|
-
targetHeight = minAllowedHeight;
|
|
627
|
-
Log.d(TAG, "Zooming out to min: " + targetWidth + "x" + targetHeight);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
// Ensure target dimensions respect calculated min/max and screen
|
|
631
|
-
// boundaries with margins
|
|
632
|
-
targetWidth = Math.max(minAllowedWidth,
|
|
633
|
-
Math.min(targetWidth, maxAllowedTargetWidth));
|
|
634
|
-
targetHeight = (int)(targetWidth / initialAspectRatio);
|
|
635
|
-
if (targetHeight < minAllowedHeight) {
|
|
636
|
-
targetHeight = minAllowedHeight;
|
|
637
|
-
targetWidth = (int)(targetHeight * initialAspectRatio);
|
|
638
|
-
}
|
|
639
|
-
if (targetHeight > maxAllowedTargetHeight) {
|
|
640
|
-
targetHeight = maxAllowedTargetHeight;
|
|
641
|
-
targetWidth = (int)(targetHeight * initialAspectRatio);
|
|
642
|
-
}
|
|
643
|
-
// Final check for width after height adjustment
|
|
644
|
-
targetWidth = Math.max(minAllowedWidth,
|
|
645
|
-
Math.min(targetWidth, maxAllowedTargetWidth));
|
|
646
|
-
|
|
647
|
-
// Instantly apply new size and update layout BEFORE starting
|
|
648
|
-
// position/size animations This helps in reducing black bars by setting
|
|
649
|
-
// the target container size first.
|
|
650
|
-
mLayoutParams.width = targetWidth;
|
|
651
|
-
mLayoutParams.height = targetHeight;
|
|
652
|
-
if (mSmallWindowView != null &&
|
|
653
|
-
mSmallWindowView.getWindowToken() != null) {
|
|
654
|
-
mWindowManager.updateViewLayout(mSmallWindowView, mLayoutParams);
|
|
655
|
-
// Also update SurfaceView's layout params to match the new window size
|
|
656
|
-
// immediately
|
|
657
|
-
if (mSurfaceView != null) {
|
|
658
|
-
android.view.ViewGroup.LayoutParams surfaceParams =
|
|
659
|
-
mSurfaceView.getLayoutParams();
|
|
660
|
-
if (surfaceParams != null) {
|
|
661
|
-
surfaceParams.width = targetWidth;
|
|
662
|
-
surfaceParams.height = targetHeight;
|
|
663
|
-
mSurfaceView.setLayoutParams(surfaceParams);
|
|
664
|
-
mSurfaceView
|
|
665
|
-
.requestLayout(); // Crucial for SurfaceView to redraw correctly
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
// Determine window corner for zoom anchor, considering margins
|
|
671
|
-
boolean isTop =
|
|
672
|
-
currentY < (screenHeight - MARGIN_TOP - MARGIN_BOTTOM) / 2 -
|
|
673
|
-
currentHeight / 2 + MARGIN_TOP;
|
|
674
|
-
boolean isLeft =
|
|
675
|
-
currentX < (screenWidth - MARGIN_LEFT - MARGIN_RIGHT) / 2 -
|
|
676
|
-
currentWidth / 2 + MARGIN_LEFT;
|
|
677
|
-
|
|
678
|
-
if (isLeft && isTop) { // Top-left
|
|
679
|
-
finalTargetX = MARGIN_LEFT;
|
|
680
|
-
finalTargetY = MARGIN_TOP;
|
|
681
|
-
} else if (!isLeft && isTop) { // Top-right
|
|
682
|
-
finalTargetX = screenWidth - targetWidth - MARGIN_RIGHT;
|
|
683
|
-
finalTargetY = MARGIN_TOP;
|
|
684
|
-
} else if (isLeft && !isTop) { // Bottom-left
|
|
685
|
-
finalTargetX = MARGIN_LEFT;
|
|
686
|
-
finalTargetY = screenHeight - targetHeight - MARGIN_BOTTOM;
|
|
687
|
-
} else { // Bottom-right
|
|
688
|
-
finalTargetX = screenWidth - targetWidth - MARGIN_RIGHT;
|
|
689
|
-
finalTargetY = screenHeight - targetHeight - MARGIN_BOTTOM;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
// Ensure target position is within drawable area
|
|
693
|
-
finalTargetX = Math.max(
|
|
694
|
-
MARGIN_LEFT,
|
|
695
|
-
Math.min(finalTargetX, screenWidth - targetWidth - MARGIN_RIGHT));
|
|
696
|
-
finalTargetY = Math.max(
|
|
697
|
-
MARGIN_TOP,
|
|
698
|
-
Math.min(finalTargetY, screenHeight - targetHeight - MARGIN_BOTTOM));
|
|
699
|
-
|
|
700
|
-
final int finalTargetWidth = targetWidth;
|
|
701
|
-
final int finalTargetHeight = targetHeight;
|
|
702
|
-
|
|
703
|
-
// Make copies for use in animator listeners
|
|
704
|
-
final int animFinalTargetX = finalTargetX;
|
|
705
|
-
final int animFinalTargetY = finalTargetY;
|
|
706
|
-
|
|
707
|
-
ValueAnimator xAnimator = ValueAnimator.ofInt(currentX, finalTargetX);
|
|
708
|
-
xAnimator.setDuration(200);
|
|
709
|
-
xAnimator.addUpdateListener(animation -> {
|
|
710
|
-
mLayoutParams.x = (Integer)animation.getAnimatedValue();
|
|
711
|
-
mWindowManager.updateViewLayout(view, mLayoutParams);
|
|
712
|
-
});
|
|
713
|
-
|
|
714
|
-
ValueAnimator yAnimator = ValueAnimator.ofInt(currentY, finalTargetY);
|
|
715
|
-
yAnimator.setDuration(200);
|
|
716
|
-
yAnimator.addUpdateListener(animation -> {
|
|
717
|
-
mLayoutParams.y = (Integer)animation.getAnimatedValue();
|
|
718
|
-
mWindowManager.updateViewLayout(view, mLayoutParams);
|
|
719
|
-
});
|
|
720
|
-
|
|
721
|
-
ValueAnimator widthAnimator =
|
|
722
|
-
ValueAnimator.ofInt(currentWidth, finalTargetWidth);
|
|
723
|
-
widthAnimator.setDuration(200);
|
|
724
|
-
widthAnimator.addUpdateListener(animation -> {
|
|
725
|
-
mLayoutParams.width = (Integer)animation.getAnimatedValue();
|
|
726
|
-
if (mSurfaceView != null) { // Ensure mSurfaceView is not null
|
|
727
|
-
android.view.ViewGroup.LayoutParams surfaceParams =
|
|
728
|
-
mSurfaceView.getLayoutParams();
|
|
729
|
-
if (surfaceParams != null) { // Ensure surfaceParams is not null
|
|
730
|
-
surfaceParams.width = mLayoutParams.width;
|
|
731
|
-
mSurfaceView.setLayoutParams(surfaceParams);
|
|
732
|
-
}
|
|
733
|
-
}
|
|
734
|
-
mWindowManager.updateViewLayout(view, mLayoutParams);
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
ValueAnimator heightAnimator =
|
|
738
|
-
ValueAnimator.ofInt(currentHeight, finalTargetHeight);
|
|
739
|
-
heightAnimator.setDuration(200);
|
|
740
|
-
heightAnimator.addUpdateListener(animation -> {
|
|
741
|
-
mLayoutParams.height = (Integer)animation.getAnimatedValue();
|
|
742
|
-
if (mSurfaceView != null) { // Ensure mSurfaceView is not null
|
|
743
|
-
android.view.ViewGroup.LayoutParams surfaceParams =
|
|
744
|
-
mSurfaceView.getLayoutParams();
|
|
745
|
-
if (surfaceParams != null) { // Ensure surfaceParams is not null
|
|
746
|
-
surfaceParams.height = mLayoutParams.height;
|
|
747
|
-
mSurfaceView.setLayoutParams(surfaceParams);
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
mWindowManager.updateViewLayout(view, mLayoutParams);
|
|
751
|
-
});
|
|
752
|
-
|
|
753
|
-
android.animation.AnimatorSet animatorSet =
|
|
754
|
-
new android.animation.AnimatorSet();
|
|
755
|
-
animatorSet.playTogether(xAnimator, yAnimator, widthAnimator,
|
|
756
|
-
heightAnimator);
|
|
757
|
-
// The isDoubleClickAnimating flag is now managed by
|
|
758
|
-
// FloatingOnTouchListener but we still need to set it within
|
|
759
|
-
// handleDoubleClick's AnimatorSet listeners to ensure it's active for the
|
|
760
|
-
// duration of this specific animation.
|
|
761
|
-
animatorSet.addListener(new android.animation.AnimatorListenerAdapter() {
|
|
762
|
-
@Override
|
|
763
|
-
public void onAnimationStart(android.animation.Animator animation) {
|
|
764
|
-
if (FloatingWindowService.this.mFloatingOnTouchListener != null) {
|
|
765
|
-
FloatingWindowService.this.mFloatingOnTouchListener
|
|
766
|
-
.isDoubleClickAnimating = true;
|
|
767
|
-
}
|
|
768
|
-
Log.d(TAG, "Double tap AnimatorSet started.");
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
@Override
|
|
772
|
-
public void onAnimationEnd(android.animation.Animator animation) {
|
|
773
|
-
if (FloatingWindowService.this.mFloatingOnTouchListener != null) {
|
|
774
|
-
FloatingWindowService.this.mFloatingOnTouchListener
|
|
775
|
-
.isDoubleClickAnimating = false;
|
|
776
|
-
}
|
|
777
|
-
// ValueAnimators update mLayoutParams continuously via their
|
|
778
|
-
// AnimatorUpdateListener. For safety, explicitly set final position
|
|
779
|
-
// values as the last update might not be exact.
|
|
780
|
-
mLayoutParams.x = animFinalTargetX;
|
|
781
|
-
mLayoutParams.y = animFinalTargetY;
|
|
782
|
-
// mLayoutParams.width and mLayoutParams.height should be at
|
|
783
|
-
// finalTargetWidth/Height due to widthAnimator and heightAnimator's
|
|
784
|
-
// updates.
|
|
785
|
-
|
|
786
|
-
// Perform a final update of the window layout with all parameters.
|
|
787
|
-
if (mSmallWindowView != null &&
|
|
788
|
-
mSmallWindowView.getWindowToken() != null) {
|
|
789
|
-
mWindowManager.updateViewLayout(mSmallWindowView, mLayoutParams);
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
// Resize SurfaceView (logic moved from postDelayed and refined)
|
|
793
|
-
if (mSurfaceView != null && mLayoutParams != null) {
|
|
794
|
-
android.view.ViewGroup.LayoutParams surfaceParams =
|
|
795
|
-
mSurfaceView.getLayoutParams();
|
|
796
|
-
if (surfaceParams != null) {
|
|
797
|
-
boolean changed = false;
|
|
798
|
-
if (surfaceParams.width != mLayoutParams.width) {
|
|
799
|
-
surfaceParams.width =
|
|
800
|
-
mLayoutParams.width; // mLayoutParams.width is at its final
|
|
801
|
-
// animated value
|
|
802
|
-
changed = true;
|
|
803
|
-
}
|
|
804
|
-
if (surfaceParams.height != mLayoutParams.height) {
|
|
805
|
-
surfaceParams.height =
|
|
806
|
-
mLayoutParams.height; // mLayoutParams.height is at its
|
|
807
|
-
// final animated value
|
|
808
|
-
changed = true;
|
|
809
|
-
}
|
|
810
|
-
if (changed) {
|
|
811
|
-
mSurfaceView.setLayoutParams(surfaceParams);
|
|
812
|
-
}
|
|
813
|
-
mSurfaceView
|
|
814
|
-
.requestLayout(); // Ensure the SurfaceView redraws correctly
|
|
815
|
-
Log.d(TAG,
|
|
816
|
-
"SurfaceView dimensions finalized in onAnimationEnd to: " +
|
|
817
|
-
mLayoutParams.width + "x" + mLayoutParams.height);
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
Log.d(TAG, "Double tap AnimatorSet ended. Final state: x=" +
|
|
821
|
-
mLayoutParams.x + ", y=" + mLayoutParams.y + ", w=" +
|
|
822
|
-
mLayoutParams.width + ", h=" + mLayoutParams.height);
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
@Override
|
|
826
|
-
public void onAnimationCancel(android.animation.Animator animation) {
|
|
827
|
-
if (FloatingWindowService.this.mFloatingOnTouchListener != null) {
|
|
828
|
-
FloatingWindowService.this.mFloatingOnTouchListener
|
|
829
|
-
.isDoubleClickAnimating = false;
|
|
830
|
-
}
|
|
831
|
-
// Animation was cancelled, so explicitly set all mLayoutParams to
|
|
832
|
-
// their final target values.
|
|
833
|
-
mLayoutParams.x = animFinalTargetX;
|
|
834
|
-
mLayoutParams.y = animFinalTargetY;
|
|
835
|
-
mLayoutParams.width = finalTargetWidth;
|
|
836
|
-
mLayoutParams.height = finalTargetHeight;
|
|
837
|
-
|
|
838
|
-
if (mSmallWindowView != null &&
|
|
839
|
-
mSmallWindowView.getWindowToken() != null) {
|
|
840
|
-
mWindowManager.updateViewLayout(mSmallWindowView, mLayoutParams);
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
// Resize SurfaceView to final target dimensions
|
|
844
|
-
if (mSurfaceView != null && mLayoutParams != null) {
|
|
845
|
-
android.view.ViewGroup.LayoutParams surfaceParams =
|
|
846
|
-
mSurfaceView.getLayoutParams();
|
|
847
|
-
if (surfaceParams != null) {
|
|
848
|
-
if (surfaceParams.width != mLayoutParams.width ||
|
|
849
|
-
surfaceParams.height != mLayoutParams.height) {
|
|
850
|
-
surfaceParams.width =
|
|
851
|
-
mLayoutParams.width; // Now finalTargetWidth
|
|
852
|
-
surfaceParams.height =
|
|
853
|
-
mLayoutParams.height; // Now finalTargetHeight
|
|
854
|
-
mSurfaceView.setLayoutParams(surfaceParams);
|
|
855
|
-
}
|
|
856
|
-
mSurfaceView
|
|
857
|
-
.requestLayout(); // Ensure the SurfaceView redraws correctly
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
Log.d(TAG,
|
|
861
|
-
"Double tap AnimatorSet cancelled. State set to targets: x=" +
|
|
862
|
-
mLayoutParams.x + ", y=" + mLayoutParams.y + ", w=" +
|
|
863
|
-
mLayoutParams.width + ", h=" + mLayoutParams.height);
|
|
864
|
-
}
|
|
865
|
-
});
|
|
866
|
-
animatorSet.start();
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
private void animateSnapToEdge(View view) {
|
|
870
|
-
// Use pre-calculated screen metrics
|
|
871
|
-
// updateScreenMetrics(); // Ensure metrics are fresh if not updated in
|
|
872
|
-
// onTouch ACTION_DOWN Screen metrics are now updated in onTouch
|
|
873
|
-
// ACTION_DOWN, so they should be current here.
|
|
874
|
-
final int screenWidth = this.screenWidth; // Make final for use in lambda
|
|
875
|
-
final int windowWidthAtAnimationStart =
|
|
876
|
-
mLayoutParams.width; // Capture width at start
|
|
877
|
-
|
|
878
|
-
int currentX =
|
|
879
|
-
mLayoutParams
|
|
880
|
-
.x; // This is the x at the moment animateSnapToEdge is called
|
|
881
|
-
int targetX;
|
|
882
|
-
|
|
883
|
-
// Determine targetX based on current position and captured width
|
|
884
|
-
if (currentX + windowWidthAtAnimationStart / 2 < screenWidth / 2) {
|
|
885
|
-
targetX = MARGIN_LEFT;
|
|
886
|
-
} else {
|
|
887
|
-
targetX = screenWidth - windowWidthAtAnimationStart - MARGIN_RIGHT;
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
Log.i(TAG, "animateSnapToEdge: currentX=" + currentX +
|
|
891
|
-
", windowWidthAtAnimStart=" + windowWidthAtAnimationStart +
|
|
892
|
-
", screenWidth=" + screenWidth + ", calculatedTargetX=" +
|
|
893
|
-
targetX + ", currentY=" + mLayoutParams.y +
|
|
894
|
-
", currentHeight=" + mLayoutParams.height);
|
|
895
|
-
|
|
896
|
-
if (currentX == targetX) {
|
|
897
|
-
Log.i(TAG, "animateSnapToEdge: Already at targetX (" + targetX +
|
|
898
|
-
"). No animation needed.");
|
|
899
|
-
return;
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
ValueAnimator snapAnimator = ValueAnimator.ofInt(currentX, targetX);
|
|
903
|
-
snapAnimator.setDuration(200);
|
|
904
|
-
snapAnimator.addUpdateListener(animation -> {
|
|
905
|
-
mLayoutParams.x = (Integer)animation.getAnimatedValue();
|
|
906
|
-
// Boundary checks using width captured at animation start
|
|
907
|
-
if (mLayoutParams.x < 0) { // Physical screen boundary
|
|
908
|
-
mLayoutParams.x = 0;
|
|
909
|
-
}
|
|
910
|
-
// Ensure the right edge does not go beyond screen width
|
|
911
|
-
if (mLayoutParams.x + windowWidthAtAnimationStart >
|
|
912
|
-
screenWidth) { // Physical screen boundary
|
|
913
|
-
mLayoutParams.x = screenWidth - windowWidthAtAnimationStart;
|
|
914
|
-
}
|
|
915
|
-
try {
|
|
916
|
-
if (mSmallWindowView != null &&
|
|
917
|
-
mSmallWindowView.getWindowToken() !=
|
|
918
|
-
null) { // Check if view is still attached
|
|
919
|
-
mWindowManager.updateViewLayout(view, mLayoutParams);
|
|
920
|
-
}
|
|
921
|
-
} catch (IllegalArgumentException e) {
|
|
922
|
-
Log.w(TAG, "animateSnapToEdge: View not attached? " + e.getMessage());
|
|
923
|
-
// Cancel animator if view is gone to prevent further errors
|
|
924
|
-
if (animation.isRunning()) {
|
|
925
|
-
animation.cancel();
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
});
|
|
929
|
-
snapAnimator.start();
|
|
930
|
-
}
|
|
931
252
|
}
|
|
932
253
|
}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -4566,7 +4566,6 @@ var TVLManager = function () {
|
|
|
4566
4566
|
var _setEnableSuperResolution_decorators;
|
|
4567
4567
|
var _setVolume_decorators;
|
|
4568
4568
|
var _setEnableIgnoreAudioInterruption_decorators;
|
|
4569
|
-
var _setAllowsVideoRendering_decorators;
|
|
4570
4569
|
_classThis = /** @class */ (function () {
|
|
4571
4570
|
function TVLManager_1() {
|
|
4572
4571
|
/** {zh}
|
|
@@ -4877,9 +4876,6 @@ var TVLManager = function () {
|
|
|
4877
4876
|
TVLManager_1.prototype.setEnableIgnoreAudioInterruption = function (enable) {
|
|
4878
4877
|
throw new Error('not implement');
|
|
4879
4878
|
};
|
|
4880
|
-
TVLManager_1.prototype.setAllowsVideoRendering = function (enable) {
|
|
4881
|
-
throw new Error('not implement');
|
|
4882
|
-
};
|
|
4883
4879
|
return TVLManager_1;
|
|
4884
4880
|
}());
|
|
4885
4881
|
__setFunctionName(_classThis, "TVLManager");
|
|
@@ -4916,7 +4912,6 @@ var TVLManager = function () {
|
|
|
4916
4912
|
_setEnableSuperResolution_decorators = [NativeMethodSync('setEnableSuperResolution:')];
|
|
4917
4913
|
_setVolume_decorators = [NativeMethodSync('setVolume:')];
|
|
4918
4914
|
_setEnableIgnoreAudioInterruption_decorators = [NativeMethodSync('setEnableIgnoreAudioInterruption:')];
|
|
4919
|
-
_setAllowsVideoRendering_decorators = [NativeMethodSync('setAllowsVideoRendering:')];
|
|
4920
4915
|
__esDecorate(_classThis, null, _static_setLogLevel_decorators, { kind: "method", name: "setLogLevel", static: true, private: false, access: { has: function (obj) { return "setLogLevel" in obj; }, get: function (obj) { return obj.setLogLevel; } }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
4921
4916
|
__esDecorate(_classThis, null, _static_getVersion_decorators, { kind: "method", name: "getVersion", static: true, private: false, access: { has: function (obj) { return "getVersion" in obj; }, get: function (obj) { return obj.getVersion; } }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
4922
4917
|
__esDecorate(_classThis, null, _static_setHttpDNSHostIP_decorators, { kind: "method", name: "setHttpDNSHostIP", static: true, private: false, access: { has: function (obj) { return "setHttpDNSHostIP" in obj; }, get: function (obj) { return obj.setHttpDNSHostIP; } }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
@@ -4944,7 +4939,6 @@ var TVLManager = function () {
|
|
|
4944
4939
|
__esDecorate(_classThis, null, _setEnableSuperResolution_decorators, { kind: "method", name: "setEnableSuperResolution", static: false, private: false, access: { has: function (obj) { return "setEnableSuperResolution" in obj; }, get: function (obj) { return obj.setEnableSuperResolution; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
4945
4940
|
__esDecorate(_classThis, null, _setVolume_decorators, { kind: "method", name: "setVolume", static: false, private: false, access: { has: function (obj) { return "setVolume" in obj; }, get: function (obj) { return obj.setVolume; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
4946
4941
|
__esDecorate(_classThis, null, _setEnableIgnoreAudioInterruption_decorators, { kind: "method", name: "setEnableIgnoreAudioInterruption", static: false, private: false, access: { has: function (obj) { return "setEnableIgnoreAudioInterruption" in obj; }, get: function (obj) { return obj.setEnableIgnoreAudioInterruption; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
4947
|
-
__esDecorate(_classThis, null, _setAllowsVideoRendering_decorators, { kind: "method", name: "setAllowsVideoRendering", static: false, private: false, access: { has: function (obj) { return "setAllowsVideoRendering" in obj; }, get: function (obj) { return obj.setAllowsVideoRendering; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
4948
4942
|
__esDecorate(null, null, _observer_decorators, { kind: "field", name: "observer", static: false, private: false, access: { has: function (obj) { return "observer" in obj; }, get: function (obj) { return obj.observer; }, set: function (obj, value) { obj.observer = value; } }, metadata: _metadata }, _observer_initializers, _observer_extraInitializers);
|
|
4949
4943
|
__esDecorate(null, null, _playerView_decorators, { kind: "field", name: "playerView", static: false, private: false, access: { has: function (obj) { return "playerView" in obj; }, get: function (obj) { return obj.playerView; }, set: function (obj, value) { obj.playerView = value; } }, metadata: _metadata }, _playerView_initializers, _playerView_extraInitializers);
|
|
4950
4944
|
__esDecorate(null, null, _volume_decorators, { kind: "field", name: "volume", static: false, private: false, access: { has: function (obj) { return "volume" in obj; }, get: function (obj) { return obj.volume; }, set: function (obj, value) { obj.volume = value; } }, metadata: _metadata }, _volume_initializers, _volume_extraInitializers);
|
|
@@ -11228,42 +11222,6 @@ var ios_PictureInPictureManagerListener = /** @class */ (function (_super) {
|
|
|
11228
11222
|
return ios_PictureInPictureManagerListener;
|
|
11229
11223
|
}(VeLivePictureInPictureManagerListener));
|
|
11230
11224
|
|
|
11231
|
-
/**
|
|
11232
|
-
* ios player pool list
|
|
11233
|
-
*/
|
|
11234
|
-
var playerPool = new Set();
|
|
11235
|
-
function handleIOS(nextAppState) {
|
|
11236
|
-
switch (nextAppState) {
|
|
11237
|
-
case 'active':
|
|
11238
|
-
playerPool.forEach(function (player) {
|
|
11239
|
-
var iosPlayer = unpackObject(player);
|
|
11240
|
-
iosPlayer.setAllowsVideoRendering(true);
|
|
11241
|
-
});
|
|
11242
|
-
break;
|
|
11243
|
-
case 'background':
|
|
11244
|
-
playerPool.forEach(function (player) {
|
|
11245
|
-
var iosPlayer = unpackObject(player);
|
|
11246
|
-
iosPlayer.setAllowsVideoRendering(false);
|
|
11247
|
-
});
|
|
11248
|
-
break;
|
|
11249
|
-
}
|
|
11250
|
-
}
|
|
11251
|
-
reactNative.AppState.addEventListener('change', function (nextAppState) {
|
|
11252
|
-
switch (reactNative.Platform.OS) {
|
|
11253
|
-
case 'android':
|
|
11254
|
-
break;
|
|
11255
|
-
case 'ios':
|
|
11256
|
-
handleIOS(nextAppState);
|
|
11257
|
-
break;
|
|
11258
|
-
}
|
|
11259
|
-
});
|
|
11260
|
-
function addPlayer(player) {
|
|
11261
|
-
playerPool.add(player);
|
|
11262
|
-
}
|
|
11263
|
-
function removePlayer(player) {
|
|
11264
|
-
playerPool.delete(player);
|
|
11265
|
-
}
|
|
11266
|
-
|
|
11267
11225
|
function runImpl(context, androidImpl, iosImpl) {
|
|
11268
11226
|
if (env.getOS() === 'android') {
|
|
11269
11227
|
var androidEngine = unpackObject(context);
|
|
@@ -11385,7 +11343,6 @@ extendsClassMethod(VeLivePlayer, 'disablePictureInPicture', function () {
|
|
|
11385
11343
|
extendsClassMethod(VeLivePlayer, 'destroy', function (origin) {
|
|
11386
11344
|
return function destroy() {
|
|
11387
11345
|
var _this = this;
|
|
11388
|
-
removePlayer(this);
|
|
11389
11346
|
return runImpl(this, function () { return __awaiter(_this, void 0, void 0, function () {
|
|
11390
11347
|
return __generator(this, function (_a) {
|
|
11391
11348
|
origin();
|
|
@@ -11697,28 +11654,14 @@ function initIOSPlayer(options) {
|
|
|
11697
11654
|
*/
|
|
11698
11655
|
function initPlayer(options) {
|
|
11699
11656
|
return __awaiter(this, void 0, void 0, function () {
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
}
|
|
11709
|
-
return [3 /*break*/, 5];
|
|
11710
|
-
case 1: return [4 /*yield*/, initAndroidPlayer(options)];
|
|
11711
|
-
case 2:
|
|
11712
|
-
player = (_b.sent());
|
|
11713
|
-
return [3 /*break*/, 6];
|
|
11714
|
-
case 3: return [4 /*yield*/, initIOSPlayer(options)];
|
|
11715
|
-
case 4:
|
|
11716
|
-
player = (_b.sent());
|
|
11717
|
-
return [3 /*break*/, 6];
|
|
11718
|
-
case 5: throw new Error('Unsupported platform');
|
|
11719
|
-
case 6:
|
|
11720
|
-
addPlayer(player);
|
|
11721
|
-
return [2 /*return*/, player];
|
|
11657
|
+
return __generator(this, function (_a) {
|
|
11658
|
+
switch (reactNative.Platform.OS) {
|
|
11659
|
+
case 'android':
|
|
11660
|
+
return [2 /*return*/, initAndroidPlayer(options)];
|
|
11661
|
+
case 'ios':
|
|
11662
|
+
return [2 /*return*/, initIOSPlayer(options)];
|
|
11663
|
+
default:
|
|
11664
|
+
throw new Error('Unsupported platform');
|
|
11722
11665
|
}
|
|
11723
11666
|
});
|
|
11724
11667
|
});
|
package/lib/module/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NativeEventEmitter, Image, Platform, requireNativeComponent,
|
|
1
|
+
import { NativeEventEmitter, Image, Platform, requireNativeComponent, NativeModules } from 'react-native';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -4564,7 +4564,6 @@ var TVLManager = function () {
|
|
|
4564
4564
|
var _setEnableSuperResolution_decorators;
|
|
4565
4565
|
var _setVolume_decorators;
|
|
4566
4566
|
var _setEnableIgnoreAudioInterruption_decorators;
|
|
4567
|
-
var _setAllowsVideoRendering_decorators;
|
|
4568
4567
|
_classThis = /** @class */ (function () {
|
|
4569
4568
|
function TVLManager_1() {
|
|
4570
4569
|
/** {zh}
|
|
@@ -4875,9 +4874,6 @@ var TVLManager = function () {
|
|
|
4875
4874
|
TVLManager_1.prototype.setEnableIgnoreAudioInterruption = function (enable) {
|
|
4876
4875
|
throw new Error('not implement');
|
|
4877
4876
|
};
|
|
4878
|
-
TVLManager_1.prototype.setAllowsVideoRendering = function (enable) {
|
|
4879
|
-
throw new Error('not implement');
|
|
4880
|
-
};
|
|
4881
4877
|
return TVLManager_1;
|
|
4882
4878
|
}());
|
|
4883
4879
|
__setFunctionName(_classThis, "TVLManager");
|
|
@@ -4914,7 +4910,6 @@ var TVLManager = function () {
|
|
|
4914
4910
|
_setEnableSuperResolution_decorators = [NativeMethodSync('setEnableSuperResolution:')];
|
|
4915
4911
|
_setVolume_decorators = [NativeMethodSync('setVolume:')];
|
|
4916
4912
|
_setEnableIgnoreAudioInterruption_decorators = [NativeMethodSync('setEnableIgnoreAudioInterruption:')];
|
|
4917
|
-
_setAllowsVideoRendering_decorators = [NativeMethodSync('setAllowsVideoRendering:')];
|
|
4918
4913
|
__esDecorate(_classThis, null, _static_setLogLevel_decorators, { kind: "method", name: "setLogLevel", static: true, private: false, access: { has: function (obj) { return "setLogLevel" in obj; }, get: function (obj) { return obj.setLogLevel; } }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
4919
4914
|
__esDecorate(_classThis, null, _static_getVersion_decorators, { kind: "method", name: "getVersion", static: true, private: false, access: { has: function (obj) { return "getVersion" in obj; }, get: function (obj) { return obj.getVersion; } }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
4920
4915
|
__esDecorate(_classThis, null, _static_setHttpDNSHostIP_decorators, { kind: "method", name: "setHttpDNSHostIP", static: true, private: false, access: { has: function (obj) { return "setHttpDNSHostIP" in obj; }, get: function (obj) { return obj.setHttpDNSHostIP; } }, metadata: _metadata }, null, _staticExtraInitializers);
|
|
@@ -4942,7 +4937,6 @@ var TVLManager = function () {
|
|
|
4942
4937
|
__esDecorate(_classThis, null, _setEnableSuperResolution_decorators, { kind: "method", name: "setEnableSuperResolution", static: false, private: false, access: { has: function (obj) { return "setEnableSuperResolution" in obj; }, get: function (obj) { return obj.setEnableSuperResolution; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
4943
4938
|
__esDecorate(_classThis, null, _setVolume_decorators, { kind: "method", name: "setVolume", static: false, private: false, access: { has: function (obj) { return "setVolume" in obj; }, get: function (obj) { return obj.setVolume; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
4944
4939
|
__esDecorate(_classThis, null, _setEnableIgnoreAudioInterruption_decorators, { kind: "method", name: "setEnableIgnoreAudioInterruption", static: false, private: false, access: { has: function (obj) { return "setEnableIgnoreAudioInterruption" in obj; }, get: function (obj) { return obj.setEnableIgnoreAudioInterruption; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
4945
|
-
__esDecorate(_classThis, null, _setAllowsVideoRendering_decorators, { kind: "method", name: "setAllowsVideoRendering", static: false, private: false, access: { has: function (obj) { return "setAllowsVideoRendering" in obj; }, get: function (obj) { return obj.setAllowsVideoRendering; } }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
4946
4940
|
__esDecorate(null, null, _observer_decorators, { kind: "field", name: "observer", static: false, private: false, access: { has: function (obj) { return "observer" in obj; }, get: function (obj) { return obj.observer; }, set: function (obj, value) { obj.observer = value; } }, metadata: _metadata }, _observer_initializers, _observer_extraInitializers);
|
|
4947
4941
|
__esDecorate(null, null, _playerView_decorators, { kind: "field", name: "playerView", static: false, private: false, access: { has: function (obj) { return "playerView" in obj; }, get: function (obj) { return obj.playerView; }, set: function (obj, value) { obj.playerView = value; } }, metadata: _metadata }, _playerView_initializers, _playerView_extraInitializers);
|
|
4948
4942
|
__esDecorate(null, null, _volume_decorators, { kind: "field", name: "volume", static: false, private: false, access: { has: function (obj) { return "volume" in obj; }, get: function (obj) { return obj.volume; }, set: function (obj, value) { obj.volume = value; } }, metadata: _metadata }, _volume_initializers, _volume_extraInitializers);
|
|
@@ -11226,42 +11220,6 @@ var ios_PictureInPictureManagerListener = /** @class */ (function (_super) {
|
|
|
11226
11220
|
return ios_PictureInPictureManagerListener;
|
|
11227
11221
|
}(VeLivePictureInPictureManagerListener));
|
|
11228
11222
|
|
|
11229
|
-
/**
|
|
11230
|
-
* ios player pool list
|
|
11231
|
-
*/
|
|
11232
|
-
var playerPool = new Set();
|
|
11233
|
-
function handleIOS(nextAppState) {
|
|
11234
|
-
switch (nextAppState) {
|
|
11235
|
-
case 'active':
|
|
11236
|
-
playerPool.forEach(function (player) {
|
|
11237
|
-
var iosPlayer = unpackObject(player);
|
|
11238
|
-
iosPlayer.setAllowsVideoRendering(true);
|
|
11239
|
-
});
|
|
11240
|
-
break;
|
|
11241
|
-
case 'background':
|
|
11242
|
-
playerPool.forEach(function (player) {
|
|
11243
|
-
var iosPlayer = unpackObject(player);
|
|
11244
|
-
iosPlayer.setAllowsVideoRendering(false);
|
|
11245
|
-
});
|
|
11246
|
-
break;
|
|
11247
|
-
}
|
|
11248
|
-
}
|
|
11249
|
-
AppState.addEventListener('change', function (nextAppState) {
|
|
11250
|
-
switch (Platform.OS) {
|
|
11251
|
-
case 'android':
|
|
11252
|
-
break;
|
|
11253
|
-
case 'ios':
|
|
11254
|
-
handleIOS(nextAppState);
|
|
11255
|
-
break;
|
|
11256
|
-
}
|
|
11257
|
-
});
|
|
11258
|
-
function addPlayer(player) {
|
|
11259
|
-
playerPool.add(player);
|
|
11260
|
-
}
|
|
11261
|
-
function removePlayer(player) {
|
|
11262
|
-
playerPool.delete(player);
|
|
11263
|
-
}
|
|
11264
|
-
|
|
11265
11223
|
function runImpl(context, androidImpl, iosImpl) {
|
|
11266
11224
|
if (env.getOS() === 'android') {
|
|
11267
11225
|
var androidEngine = unpackObject(context);
|
|
@@ -11383,7 +11341,6 @@ extendsClassMethod(VeLivePlayer, 'disablePictureInPicture', function () {
|
|
|
11383
11341
|
extendsClassMethod(VeLivePlayer, 'destroy', function (origin) {
|
|
11384
11342
|
return function destroy() {
|
|
11385
11343
|
var _this = this;
|
|
11386
|
-
removePlayer(this);
|
|
11387
11344
|
return runImpl(this, function () { return __awaiter(_this, void 0, void 0, function () {
|
|
11388
11345
|
return __generator(this, function (_a) {
|
|
11389
11346
|
origin();
|
|
@@ -11695,28 +11652,14 @@ function initIOSPlayer(options) {
|
|
|
11695
11652
|
*/
|
|
11696
11653
|
function initPlayer(options) {
|
|
11697
11654
|
return __awaiter(this, void 0, void 0, function () {
|
|
11698
|
-
|
|
11699
|
-
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
}
|
|
11707
|
-
return [3 /*break*/, 5];
|
|
11708
|
-
case 1: return [4 /*yield*/, initAndroidPlayer(options)];
|
|
11709
|
-
case 2:
|
|
11710
|
-
player = (_b.sent());
|
|
11711
|
-
return [3 /*break*/, 6];
|
|
11712
|
-
case 3: return [4 /*yield*/, initIOSPlayer(options)];
|
|
11713
|
-
case 4:
|
|
11714
|
-
player = (_b.sent());
|
|
11715
|
-
return [3 /*break*/, 6];
|
|
11716
|
-
case 5: throw new Error('Unsupported platform');
|
|
11717
|
-
case 6:
|
|
11718
|
-
addPlayer(player);
|
|
11719
|
-
return [2 /*return*/, player];
|
|
11655
|
+
return __generator(this, function (_a) {
|
|
11656
|
+
switch (Platform.OS) {
|
|
11657
|
+
case 'android':
|
|
11658
|
+
return [2 /*return*/, initAndroidPlayer(options)];
|
|
11659
|
+
case 'ios':
|
|
11660
|
+
return [2 /*return*/, initIOSPlayer(options)];
|
|
11661
|
+
default:
|
|
11662
|
+
throw new Error('Unsupported platform');
|
|
11720
11663
|
}
|
|
11721
11664
|
});
|
|
11722
11665
|
});
|
|
@@ -63,7 +63,6 @@ export declare class TVLManager {
|
|
|
63
63
|
setEnableSuperResolution(enable: BOOL): void;
|
|
64
64
|
setVolume(volume: float): void;
|
|
65
65
|
setEnableIgnoreAudioInterruption(enable: BOOL): void;
|
|
66
|
-
setAllowsVideoRendering(enable: BOOL): void;
|
|
67
66
|
}
|
|
68
67
|
export declare enum VeLivePlayerType {
|
|
69
68
|
|
package/package.json
CHANGED