Skip to content

Commit

Permalink
Merge pull request #604 from takahirom/takahirom/add-workaround-for-o…
Browse files Browse the repository at this point in the history
…verlap/2024-12-12

Add overlap workaround
  • Loading branch information
takahirom authored Dec 15, 2024
2 parents f508092 + 7382573 commit c904c1d
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,44 @@ fun SemanticsNode.fetchImage(recordOptions: RoborazziOptions.RecordOptions): Bit
val locationInWindow = IntArray(2)
view.getLocationInWindow(locationInWindow)
nodeBoundsRect.offset(locationInWindow[0], locationInWindow[1])
return windowToUse.decorView.fetchImage(recordOptions = recordOptions)?.crop(nodeBoundsRect, recordOptions)
if (dialogWindow != null) {
return windowToUse.decorView.fetchImage(recordOptions = recordOptions)
?.crop(nodeBoundsRect, recordOptions)
}

// Experimental workaround to avoid content overlapping when capturing the bitmap.
val actionBarWorkaroundIsOn = getSystemProperty(
"roborazzi.compose.actionbar.overlap.fix",
"true"
) == "true"

// For SDK 35 and above, if we have an ActionBar scenario
// we will draw the bitmap directly from the ComposeView to avoid content overlapping.
val shouldUseComposeCapture = actionBarWorkaroundIsOn &&
Build.VERSION.SDK_INT >= 35 &&
windowToUse.hasFeature(Window.FEATURE_ACTION_BAR) &&
view.getActivity()?.actionBar != null &&
view.getActivity()?.actionBar?.isShowing == true
if (shouldUseComposeCapture) {
roborazziReportLog(
"Hiding the ActionBar to avoid content overlap issues during capture.\n" +
"This workaround is used when an ActionBar is present and the SDK version is 35 or higher.\n" +
"Hiding the ActionBar might cause slight performance overhead due to layout invalidation.\n" +
"We recommend setting the theme using <application android:theme=\"@android:style/Theme.Material.NoActionBar\" /> in your test/AndroidManifest.xml to avoid this workaround.\n" +
"If you are intentionally using an ActionBar, you can disable this workaround by setting the gradle property 'roborazzi.compose.actionbar.overlap.fix' to false.\n" +
"This problem is tracked in https://issuetracker.google.com/issues/383368165"
)
return try {
view.getActivity()?.actionBar?.hide()
windowToUse.decorView.fetchImage(recordOptions = recordOptions)
?.crop(nodeBoundsRect, recordOptions)
} finally {
view.getActivity()?.actionBar?.show()
}
}

return windowToUse.decorView.fetchImage(recordOptions = recordOptions)
?.crop(nodeBoundsRect, recordOptions)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ internal fun View.generateBitmapFromDraw(
bitmapFuture.set(destBitmap)
}

private fun View.getActivity(): Activity? {
internal fun View.getActivity(): Activity? {
fun Context.getActivity(): Activity? {
return when (this) {
is Activity -> this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import androidx.compose.ui.unit.dp
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.github.takahirom.roborazzi.RoborazziRule
import com.github.takahirom.roborazzi.RoborazziTransparentActivity
import com.github.takahirom.roborazzi.captureRoboImage
import org.junit.Rule
import org.junit.Test
Expand All @@ -45,8 +44,8 @@ class DefaultThemeComposeTest {
val appContext: Application = ApplicationProvider.getApplicationContext()
Shadows.shadowOf(appContext.packageManager).addActivityIfNotPresent(
ComponentName(
appContext.packageName,
DefaultThemeActivity::class.java.name,
appContext,
DefaultThemeActivity::class.java,
)
)
}
Expand Down

0 comments on commit c904c1d

Please sign in to comment.