Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ internal class ViewTransitionSnapshotManager(
) : UIManagerListener {

companion object {
private fun captureSoftwareBitmap(view: View): Bitmap {
val bitmap = createBitmap(view.width, view.height)
view.draw(Canvas(bitmap))
return bitmap
private fun captureSoftwareBitmap(view: View): Bitmap? {
if (view.width > 0 && view.height > 0) {
val bitmap = createBitmap(view.width, view.height)
view.draw(Canvas(bitmap))
return bitmap
}
return null
}
}

Expand Down Expand Up @@ -96,7 +99,7 @@ internal class ViewTransitionSnapshotManager(
} else {
// Software fallback runs synchronously, so onBitmapCaptured always
// completes before setViewSnapshot is called.
onBitmapCaptured(reactTag, captureSoftwareBitmap(view))
captureSoftwareBitmap(view)?.let { onBitmapCaptured(reactTag, it) }
}
}
}
Expand All @@ -106,9 +109,16 @@ internal class ViewTransitionSnapshotManager(
val location = IntArray(2)
view.getLocationInWindow(location)

val viewWidth = view.width
val viewHeight = view.height

if (viewWidth <= 0 || viewHeight <= 0) {
// Nothing to capture.
return
}

// The view's rect in window coordinates.
val viewRect =
Rect(location[0], location[1], location[0] + view.width, location[1] + view.height)
val viewRect = Rect(location[0], location[1], location[0] + viewWidth, location[1] + viewHeight)

// Clamp to window bounds — PixelCopy only captures what's visible on the
// window surface. Without clamping, off-screen portions are black/empty
Expand Down Expand Up @@ -144,23 +154,24 @@ internal class ViewTransitionSnapshotManager(
if (copyResult == PixelCopy.SUCCESS) {
// Compose the clamped capture into a full-size bitmap at the
// correct offset so it aligns with the pseudo-element's bounds.
val fullBitmap = createBitmap(view.width, view.height)
val fullBitmap = createBitmap(viewWidth, viewHeight)
Canvas(fullBitmap)
.drawBitmap(clampedBitmap, offsetX.toFloat(), offsetY.toFloat(), null)
clampedBitmap.recycle()
onBitmapCaptured(reactTag, fullBitmap)
} else {
// Fall back to software rendering if the view is still valid.
clampedBitmap.recycle()
onBitmapCaptured(reactTag, captureSoftwareBitmap(view))
captureSoftwareBitmap(view)?.let { onBitmapCaptured(reactTag, it) }
}
},
mainHandler,
)
} catch (e: IllegalArgumentException) {
// Window surface may have been destroyed (e.g., device idle/sleep).
// Fall back to software rendering.
// Fall back to software rendering if the view is still valid.
clampedBitmap.recycle()
onBitmapCaptured(reactTag, captureSoftwareBitmap(view))
captureSoftwareBitmap(view)?.let { onBitmapCaptured(reactTag, it) }
}
}

Expand Down
Loading