@capgo/camera-preview 7.4.0-alpha.19 → 7.4.0-alpha.22
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/ahm/capacitor/camera/preview/CameraPreview.java +235 -14
- package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraXView.java +831 -252
- package/ios/Sources/CapgoCameraPreviewPlugin/CameraController.swift +35 -10
- package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +1 -1
- package/package.json +1 -1
|
@@ -61,6 +61,8 @@ public class CameraPreview
|
|
|
61
61
|
extends Plugin
|
|
62
62
|
implements CameraXView.CameraXViewListener {
|
|
63
63
|
|
|
64
|
+
private static final String TAG = "CameraPreview CameraXView";
|
|
65
|
+
|
|
64
66
|
static final String CAMERA_WITH_AUDIO_PERMISSION_ALIAS = "cameraWithAudio";
|
|
65
67
|
static final String CAMERA_ONLY_PERMISSION_ALIAS = "cameraOnly";
|
|
66
68
|
static final String CAMERA_WITH_LOCATION_PERMISSION_ALIAS =
|
|
@@ -1031,7 +1033,12 @@ public class CameraPreview
|
|
|
1031
1033
|
.orientation;
|
|
1032
1034
|
if (current != lastOrientation) {
|
|
1033
1035
|
lastOrientation = current;
|
|
1034
|
-
|
|
1036
|
+
// Post to next frame so WebView has updated bounds before we recompute layout
|
|
1037
|
+
getBridge()
|
|
1038
|
+
.getActivity()
|
|
1039
|
+
.getWindow()
|
|
1040
|
+
.getDecorView()
|
|
1041
|
+
.post(() -> handleOrientationChange());
|
|
1035
1042
|
}
|
|
1036
1043
|
}
|
|
1037
1044
|
};
|
|
@@ -1044,13 +1051,115 @@ public class CameraPreview
|
|
|
1044
1051
|
|
|
1045
1052
|
private void handleOrientationChange() {
|
|
1046
1053
|
if (cameraXView == null || !cameraXView.isRunning()) return;
|
|
1054
|
+
|
|
1055
|
+
Log.d(
|
|
1056
|
+
TAG,
|
|
1057
|
+
"======================== ORIENTATION CHANGE DETECTED ========================"
|
|
1058
|
+
);
|
|
1059
|
+
|
|
1060
|
+
// Get comprehensive display and orientation information
|
|
1061
|
+
android.util.DisplayMetrics metrics = getContext()
|
|
1062
|
+
.getResources()
|
|
1063
|
+
.getDisplayMetrics();
|
|
1064
|
+
int screenWidthPx = metrics.widthPixels;
|
|
1065
|
+
int screenHeightPx = metrics.heightPixels;
|
|
1066
|
+
float density = metrics.density;
|
|
1067
|
+
int screenWidthDp = (int) (screenWidthPx / density);
|
|
1068
|
+
int screenHeightDp = (int) (screenHeightPx / density);
|
|
1069
|
+
|
|
1070
|
+
int current = getContext().getResources().getConfiguration().orientation;
|
|
1071
|
+
Log.d(TAG, "New orientation: " + current + " (1=PORTRAIT, 2=LANDSCAPE)");
|
|
1072
|
+
Log.d(
|
|
1073
|
+
TAG,
|
|
1074
|
+
"Screen dimensions - Pixels: " +
|
|
1075
|
+
screenWidthPx +
|
|
1076
|
+
"x" +
|
|
1077
|
+
screenHeightPx +
|
|
1078
|
+
", DP: " +
|
|
1079
|
+
screenWidthDp +
|
|
1080
|
+
"x" +
|
|
1081
|
+
screenHeightDp +
|
|
1082
|
+
", Density: " +
|
|
1083
|
+
density
|
|
1084
|
+
);
|
|
1085
|
+
|
|
1086
|
+
// Get WebView dimensions before rotation
|
|
1087
|
+
WebView webView = getBridge().getWebView();
|
|
1088
|
+
int webViewWidth = webView.getWidth();
|
|
1089
|
+
int webViewHeight = webView.getHeight();
|
|
1090
|
+
Log.d(TAG, "WebView dimensions: " + webViewWidth + "x" + webViewHeight);
|
|
1091
|
+
|
|
1092
|
+
// Get current preview bounds before rotation
|
|
1093
|
+
int[] oldBounds = cameraXView.getCurrentPreviewBounds();
|
|
1094
|
+
Log.d(
|
|
1095
|
+
TAG,
|
|
1096
|
+
"Current preview bounds before rotation: x=" +
|
|
1097
|
+
oldBounds[0] +
|
|
1098
|
+
", y=" +
|
|
1099
|
+
oldBounds[1] +
|
|
1100
|
+
", width=" +
|
|
1101
|
+
oldBounds[2] +
|
|
1102
|
+
", height=" +
|
|
1103
|
+
oldBounds[3]
|
|
1104
|
+
);
|
|
1105
|
+
|
|
1047
1106
|
getBridge()
|
|
1048
1107
|
.getActivity()
|
|
1049
1108
|
.runOnUiThread(() -> {
|
|
1050
1109
|
// Reapply current aspect ratio to recompute layout, then emit screenResize
|
|
1051
1110
|
String ar = cameraXView.getAspectRatio();
|
|
1052
|
-
|
|
1111
|
+
Log.d(TAG, "Reapplying aspect ratio: " + ar);
|
|
1112
|
+
|
|
1113
|
+
// Re-get dimensions after potential layout pass
|
|
1114
|
+
android.util.DisplayMetrics newMetrics = getContext()
|
|
1115
|
+
.getResources()
|
|
1116
|
+
.getDisplayMetrics();
|
|
1117
|
+
int newScreenWidthPx = newMetrics.widthPixels;
|
|
1118
|
+
int newScreenHeightPx = newMetrics.heightPixels;
|
|
1119
|
+
int newWebViewWidth = webView.getWidth();
|
|
1120
|
+
int newWebViewHeight = webView.getHeight();
|
|
1121
|
+
|
|
1122
|
+
Log.d(
|
|
1123
|
+
TAG,
|
|
1124
|
+
"New screen dimensions after rotation: " +
|
|
1125
|
+
newScreenWidthPx +
|
|
1126
|
+
"x" +
|
|
1127
|
+
newScreenHeightPx
|
|
1128
|
+
);
|
|
1129
|
+
Log.d(
|
|
1130
|
+
TAG,
|
|
1131
|
+
"New WebView dimensions after rotation: " +
|
|
1132
|
+
newWebViewWidth +
|
|
1133
|
+
"x" +
|
|
1134
|
+
newWebViewHeight
|
|
1135
|
+
);
|
|
1136
|
+
|
|
1137
|
+
// Force aspect ratio recalculation on orientation change
|
|
1138
|
+
cameraXView.forceAspectRatioRecalculation(ar, null, null, () -> {
|
|
1053
1139
|
int[] bounds = cameraXView.getCurrentPreviewBounds();
|
|
1140
|
+
Log.d(
|
|
1141
|
+
TAG,
|
|
1142
|
+
"New bounds after orientation change: x=" +
|
|
1143
|
+
bounds[0] +
|
|
1144
|
+
", y=" +
|
|
1145
|
+
bounds[1] +
|
|
1146
|
+
", width=" +
|
|
1147
|
+
bounds[2] +
|
|
1148
|
+
", height=" +
|
|
1149
|
+
bounds[3]
|
|
1150
|
+
);
|
|
1151
|
+
Log.d(
|
|
1152
|
+
TAG,
|
|
1153
|
+
"Bounds change: deltaX=" +
|
|
1154
|
+
(bounds[0] - oldBounds[0]) +
|
|
1155
|
+
", deltaY=" +
|
|
1156
|
+
(bounds[1] - oldBounds[1]) +
|
|
1157
|
+
", deltaWidth=" +
|
|
1158
|
+
(bounds[2] - oldBounds[2]) +
|
|
1159
|
+
", deltaHeight=" +
|
|
1160
|
+
(bounds[3] - oldBounds[3])
|
|
1161
|
+
);
|
|
1162
|
+
|
|
1054
1163
|
JSObject data = new JSObject();
|
|
1055
1164
|
data.put("x", bounds[0]);
|
|
1056
1165
|
data.put("y", bounds[1]);
|
|
@@ -1059,10 +1168,6 @@ public class CameraPreview
|
|
|
1059
1168
|
notifyListeners("screenResize", data);
|
|
1060
1169
|
|
|
1061
1170
|
// Also emit orientationChange with a unified string value
|
|
1062
|
-
int current = getContext()
|
|
1063
|
-
.getResources()
|
|
1064
|
-
.getConfiguration()
|
|
1065
|
-
.orientation;
|
|
1066
1171
|
String o;
|
|
1067
1172
|
if (current == Configuration.ORIENTATION_PORTRAIT) {
|
|
1068
1173
|
o = "portrait";
|
|
@@ -1074,6 +1179,11 @@ public class CameraPreview
|
|
|
1074
1179
|
JSObject oData = new JSObject();
|
|
1075
1180
|
oData.put("orientation", o);
|
|
1076
1181
|
notifyListeners("orientationChange", oData);
|
|
1182
|
+
|
|
1183
|
+
Log.d(
|
|
1184
|
+
TAG,
|
|
1185
|
+
"================================================================================"
|
|
1186
|
+
);
|
|
1077
1187
|
});
|
|
1078
1188
|
});
|
|
1079
1189
|
}
|
|
@@ -1171,11 +1281,116 @@ public class CameraPreview
|
|
|
1171
1281
|
Log.d("CameraPreview", "12. PIXEL RATIO - " + pixelRatio);
|
|
1172
1282
|
Log.d("CameraPreview", "========================");
|
|
1173
1283
|
|
|
1284
|
+
// Calculate logical values with proper rounding to avoid sub-pixel issues
|
|
1285
|
+
double logicalWidth = width / pixelRatio;
|
|
1286
|
+
double logicalHeight = height / pixelRatio;
|
|
1287
|
+
double logicalX = x / pixelRatio;
|
|
1288
|
+
double logicalY = relativeY / pixelRatio;
|
|
1289
|
+
|
|
1290
|
+
// Log exact calculations to debug one-pixel difference
|
|
1291
|
+
Log.d("CameraPreview", "========================");
|
|
1292
|
+
Log.d("CameraPreview", "FINAL POSITION CALCULATIONS:");
|
|
1293
|
+
Log.d(
|
|
1294
|
+
"CameraPreview",
|
|
1295
|
+
"Pixel values: x=" +
|
|
1296
|
+
x +
|
|
1297
|
+
", y=" +
|
|
1298
|
+
relativeY +
|
|
1299
|
+
", width=" +
|
|
1300
|
+
width +
|
|
1301
|
+
", height=" +
|
|
1302
|
+
height
|
|
1303
|
+
);
|
|
1304
|
+
Log.d("CameraPreview", "Pixel ratio: " + pixelRatio);
|
|
1305
|
+
Log.d(
|
|
1306
|
+
"CameraPreview",
|
|
1307
|
+
"Logical values (exact): x=" +
|
|
1308
|
+
logicalX +
|
|
1309
|
+
", y=" +
|
|
1310
|
+
logicalY +
|
|
1311
|
+
", width=" +
|
|
1312
|
+
logicalWidth +
|
|
1313
|
+
", height=" +
|
|
1314
|
+
logicalHeight
|
|
1315
|
+
);
|
|
1316
|
+
Log.d(
|
|
1317
|
+
"CameraPreview",
|
|
1318
|
+
"Logical values (rounded): x=" +
|
|
1319
|
+
Math.round(logicalX) +
|
|
1320
|
+
", y=" +
|
|
1321
|
+
Math.round(logicalY) +
|
|
1322
|
+
", width=" +
|
|
1323
|
+
Math.round(logicalWidth) +
|
|
1324
|
+
", height=" +
|
|
1325
|
+
Math.round(logicalHeight)
|
|
1326
|
+
);
|
|
1327
|
+
|
|
1328
|
+
// Check if previewContainer has any padding or margin that might cause offset
|
|
1329
|
+
if (cameraXView != null) {
|
|
1330
|
+
View previewContainer = cameraXView.getPreviewContainer();
|
|
1331
|
+
if (previewContainer != null) {
|
|
1332
|
+
Log.d(
|
|
1333
|
+
"CameraPreview",
|
|
1334
|
+
"PreviewContainer padding: left=" +
|
|
1335
|
+
previewContainer.getPaddingLeft() +
|
|
1336
|
+
", top=" +
|
|
1337
|
+
previewContainer.getPaddingTop() +
|
|
1338
|
+
", right=" +
|
|
1339
|
+
previewContainer.getPaddingRight() +
|
|
1340
|
+
", bottom=" +
|
|
1341
|
+
previewContainer.getPaddingBottom()
|
|
1342
|
+
);
|
|
1343
|
+
ViewGroup.LayoutParams params = previewContainer.getLayoutParams();
|
|
1344
|
+
if (params instanceof ViewGroup.MarginLayoutParams) {
|
|
1345
|
+
ViewGroup.MarginLayoutParams marginParams =
|
|
1346
|
+
(ViewGroup.MarginLayoutParams) params;
|
|
1347
|
+
Log.d(
|
|
1348
|
+
"CameraPreview",
|
|
1349
|
+
"PreviewContainer margins: left=" +
|
|
1350
|
+
marginParams.leftMargin +
|
|
1351
|
+
", top=" +
|
|
1352
|
+
marginParams.topMargin +
|
|
1353
|
+
", right=" +
|
|
1354
|
+
marginParams.rightMargin +
|
|
1355
|
+
", bottom=" +
|
|
1356
|
+
marginParams.bottomMargin
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
Log.d("CameraPreview", "========================");
|
|
1362
|
+
|
|
1174
1363
|
JSObject result = new JSObject();
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
result.put("
|
|
1364
|
+
// Return values with proper rounding to avoid gaps
|
|
1365
|
+
// For positions (x, y): floor to avoid gaps at top/left
|
|
1366
|
+
// For dimensions (width, height): ceil to avoid gaps at bottom/right
|
|
1367
|
+
result.put("width", Math.floor(logicalWidth));
|
|
1368
|
+
result.put("height", Math.floor(logicalHeight));
|
|
1369
|
+
result.put("x", Math.ceil(logicalX));
|
|
1370
|
+
result.put("y", Math.ceil(logicalY));
|
|
1371
|
+
|
|
1372
|
+
// Log what we're returning
|
|
1373
|
+
Log.d(
|
|
1374
|
+
"CameraPreview",
|
|
1375
|
+
"Returning to JS - x: " +
|
|
1376
|
+
Math.ceil(logicalX) +
|
|
1377
|
+
" (from " +
|
|
1378
|
+
logicalX +
|
|
1379
|
+
"), y: " +
|
|
1380
|
+
Math.ceil(logicalY) +
|
|
1381
|
+
" (from " +
|
|
1382
|
+
logicalY +
|
|
1383
|
+
"), width: " +
|
|
1384
|
+
Math.floor(logicalWidth) +
|
|
1385
|
+
" (from " +
|
|
1386
|
+
logicalWidth +
|
|
1387
|
+
"), height: " +
|
|
1388
|
+
Math.floor(logicalHeight) +
|
|
1389
|
+
" (from " +
|
|
1390
|
+
logicalHeight +
|
|
1391
|
+
")"
|
|
1392
|
+
);
|
|
1393
|
+
|
|
1179
1394
|
call.resolve(result);
|
|
1180
1395
|
bridge.releaseCall(call);
|
|
1181
1396
|
cameraStartCallbackId = null; // Prevent re-use
|
|
@@ -1281,10 +1496,16 @@ public class CameraPreview
|
|
|
1281
1496
|
float pixelRatio = metrics.density;
|
|
1282
1497
|
|
|
1283
1498
|
JSObject ret = new JSObject();
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1499
|
+
// Use same rounding strategy as start method
|
|
1500
|
+
double x = cameraXView.getPreviewX() / pixelRatio;
|
|
1501
|
+
double y = cameraXView.getPreviewY() / pixelRatio;
|
|
1502
|
+
double width = cameraXView.getPreviewWidth() / pixelRatio;
|
|
1503
|
+
double height = cameraXView.getPreviewHeight() / pixelRatio;
|
|
1504
|
+
|
|
1505
|
+
ret.put("x", Math.ceil(x));
|
|
1506
|
+
ret.put("y", Math.ceil(y));
|
|
1507
|
+
ret.put("width", Math.floor(width));
|
|
1508
|
+
ret.put("height", Math.floor(height));
|
|
1288
1509
|
call.resolve(ret);
|
|
1289
1510
|
}
|
|
1290
1511
|
|