react-native-morph-card 0.1.1 → 0.1.3
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.
|
@@ -225,23 +225,18 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
/**
|
|
228
|
-
* Walk the view tree and hide any screen container that isn't
|
|
229
|
-
* This catches modal screens added to separate ScreenStacks.
|
|
228
|
+
* Walk the view tree and hide any screen container that isn't already known.
|
|
229
|
+
* This catches modal screens added to separate ScreenStacks (e.g. transparentModal).
|
|
230
230
|
*/
|
|
231
|
-
private fun hideNewScreenContainers(root: ViewGroup,
|
|
231
|
+
private fun hideNewScreenContainers(root: ViewGroup, knownScreens: Set<View>) {
|
|
232
232
|
fun walk(group: ViewGroup) {
|
|
233
233
|
val name = group.javaClass.name
|
|
234
234
|
if (name.contains("ScreenStack") || name.contains("ScreenContainer")) {
|
|
235
235
|
for (i in 0 until group.childCount) {
|
|
236
236
|
val child = group.getChildAt(i)
|
|
237
|
-
if (child
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
val isSourceAncestor = isAncestorOf(childScreen, sourceScreen)
|
|
241
|
-
if (!isSourceAncestor) {
|
|
242
|
-
childScreen.visibility = View.INVISIBLE
|
|
243
|
-
Log.d(TAG, "preDraw: hid screen container ${childScreen.javaClass.simpleName}")
|
|
244
|
-
}
|
|
237
|
+
if (!knownScreens.contains(child) && child.visibility == View.VISIBLE) {
|
|
238
|
+
child.visibility = View.INVISIBLE
|
|
239
|
+
Log.d(TAG, "preDraw: hid new screen ${child.javaClass.simpleName} in ${group.javaClass.simpleName}")
|
|
245
240
|
}
|
|
246
241
|
}
|
|
247
242
|
}
|
|
@@ -253,14 +248,25 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
253
248
|
walk(root)
|
|
254
249
|
}
|
|
255
250
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
251
|
+
/**
|
|
252
|
+
* Collect all current children of ScreenStack/ScreenContainer views.
|
|
253
|
+
*/
|
|
254
|
+
private fun collectExistingScreens(root: ViewGroup): Set<View> {
|
|
255
|
+
val screens = mutableSetOf<View>()
|
|
256
|
+
fun walk(group: ViewGroup) {
|
|
257
|
+
val name = group.javaClass.name
|
|
258
|
+
if (name.contains("ScreenStack") || name.contains("ScreenContainer")) {
|
|
259
|
+
for (i in 0 until group.childCount) {
|
|
260
|
+
screens.add(group.getChildAt(i))
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (i in 0 until group.childCount) {
|
|
264
|
+
val child = group.getChildAt(i)
|
|
265
|
+
if (child is ViewGroup) walk(child)
|
|
266
|
+
}
|
|
262
267
|
}
|
|
263
|
-
|
|
268
|
+
walk(root)
|
|
269
|
+
return screens
|
|
264
270
|
}
|
|
265
271
|
|
|
266
272
|
private fun removeHierarchyListener() {
|
|
@@ -344,9 +350,10 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
344
350
|
// Also install a pre-draw listener on the DecorView to catch modal screens
|
|
345
351
|
// that are added to a different ScreenStack (e.g. transparentModal).
|
|
346
352
|
// This fires before every frame draw, so we can hide screens before they render.
|
|
347
|
-
val
|
|
353
|
+
val knownScreens = collectExistingScreens(decorView)
|
|
354
|
+
Log.d(TAG, "prepareExpand: tracking ${knownScreens.size} existing screens")
|
|
348
355
|
val pdListener = ViewTreeObserver.OnPreDrawListener {
|
|
349
|
-
hideNewScreenContainers(decorView,
|
|
356
|
+
hideNewScreenContainers(decorView, knownScreens)
|
|
350
357
|
true
|
|
351
358
|
}
|
|
352
359
|
decorView.viewTreeObserver.addOnPreDrawListener(pdListener)
|
|
@@ -355,7 +362,18 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
355
362
|
// Capture snapshot
|
|
356
363
|
val cardImage = captureSnapshot()
|
|
357
364
|
|
|
358
|
-
// Create overlay
|
|
365
|
+
// Create a full-screen overlay container that blocks the modal target screen
|
|
366
|
+
// from being visible. We use a transparent overlay — the source screen remains
|
|
367
|
+
// visible underneath. The overlay just ensures our card wrapper is above everything.
|
|
368
|
+
val fullScreenOverlay = FrameLayout(context)
|
|
369
|
+
fullScreenOverlay.layoutParams = FrameLayout.LayoutParams(
|
|
370
|
+
FrameLayout.LayoutParams.MATCH_PARENT,
|
|
371
|
+
FrameLayout.LayoutParams.MATCH_PARENT
|
|
372
|
+
)
|
|
373
|
+
// Intercept all touches while overlay is up
|
|
374
|
+
fullScreenOverlay.isClickable = true
|
|
375
|
+
|
|
376
|
+
// Create card overlay at source position (on top of screen capture)
|
|
359
377
|
val bgColor = cardBgColor
|
|
360
378
|
val wrapper = FrameLayout(context)
|
|
361
379
|
wrapper.layoutParams = FrameLayout.LayoutParams(cardWidth.toInt(), cardHeight.toInt())
|
|
@@ -373,9 +391,11 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
373
391
|
content.scaleType = ImageView.ScaleType.FIT_XY
|
|
374
392
|
content.layoutParams = FrameLayout.LayoutParams(cardWidth.toInt(), cardHeight.toInt())
|
|
375
393
|
wrapper.addView(content)
|
|
394
|
+
wrapper.tag = "morphCardWrapper"
|
|
395
|
+
fullScreenOverlay.addView(wrapper)
|
|
376
396
|
|
|
377
|
-
decorView.addView(
|
|
378
|
-
overlayContainer =
|
|
397
|
+
decorView.addView(fullScreenOverlay)
|
|
398
|
+
overlayContainer = fullScreenOverlay
|
|
379
399
|
|
|
380
400
|
// Hide source card — overlay covers it
|
|
381
401
|
alpha = 0f
|
|
@@ -461,7 +481,9 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
461
481
|
Log.d(TAG, "animateExpand: pendingTarget w=${pendingTargetWidth} h=${pendingTargetHeight} br=${pendingTargetBorderRadius}")
|
|
462
482
|
|
|
463
483
|
val dur = duration.toLong()
|
|
464
|
-
|
|
484
|
+
// Find the card wrapper inside the full-screen overlay
|
|
485
|
+
val cardWrapper = wrapper.findViewWithTag<FrameLayout>("morphCardWrapper") ?: wrapper
|
|
486
|
+
val content = if (cardWrapper.childCount > 0) cardWrapper.getChildAt(0) else null
|
|
465
487
|
|
|
466
488
|
// Compute content offset for wrapper mode
|
|
467
489
|
val contentCx = if (hasWrapper && pendingContentCentered) (targetWidthPx - cardWidth) / 2f else 0f
|
|
@@ -479,13 +501,14 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
479
501
|
|
|
480
502
|
animator.addUpdateListener { anim ->
|
|
481
503
|
val t = anim.animatedValue as Float
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
504
|
+
|
|
505
|
+
cardWrapper.x = lerp(cardLeft, targetLeft, t)
|
|
506
|
+
cardWrapper.y = lerp(cardTop, targetTop, t)
|
|
507
|
+
val lp = cardWrapper.layoutParams
|
|
485
508
|
lp.width = lerp(cardWidth, targetWidthPx, t).toInt()
|
|
486
509
|
lp.height = lerp(cardHeight, targetHeightPx, t).toInt()
|
|
487
|
-
|
|
488
|
-
setRoundedCorners(
|
|
510
|
+
cardWrapper.layoutParams = lp
|
|
511
|
+
setRoundedCorners(cardWrapper, lerp(cardCornerRadiusPx, targetCornerRadiusPx, t))
|
|
489
512
|
|
|
490
513
|
if (content != null) {
|
|
491
514
|
if (hasWrapper) {
|
|
@@ -562,8 +585,9 @@ class MorphCardSourceView(context: Context) : ReactViewGroup(context) {
|
|
|
562
585
|
return
|
|
563
586
|
}
|
|
564
587
|
|
|
565
|
-
// Get the bitmap from the overlay
|
|
566
|
-
val
|
|
588
|
+
// Get the bitmap from the card wrapper inside the overlay
|
|
589
|
+
val cardWrap = overlay.findViewWithTag<FrameLayout>("morphCardWrapper") ?: overlay
|
|
590
|
+
val origImg = if (cardWrap.childCount > 0) cardWrap.getChildAt(0) as? ImageView else null
|
|
567
591
|
val bitmap = if (origImg != null) {
|
|
568
592
|
// Extract the bitmap from the drawable
|
|
569
593
|
val drawable = origImg.drawable
|
package/package.json
CHANGED