diff --git a/example/src/Tests/Screens/Snapshot5.tsx b/example/src/Tests/Screens/Snapshot5.tsx
new file mode 100644
index 0000000000..1218a0dfa1
--- /dev/null
+++ b/example/src/Tests/Screens/Snapshot5.tsx
@@ -0,0 +1,68 @@
+import React from "react";
+import { ScrollView, StyleSheet, View } from "react-native";
+
+export const Snapshot5 = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+const Component = () => {
+ return (
+ <>
+ {
+ ref?.scrollTo({ y: 200 });
+ }}
+ >
+
+
+
+
+
+ {
+ ref?.scrollTo({ x: 200 });
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+
+const styles = StyleSheet.create({
+ view: {
+ flex: 1,
+ backgroundColor: "yellow",
+ },
+ scrollview: {
+ padding: 14,
+ paddingTop: 100,
+ maxHeight: 150,
+ },
+ scrollViewHorizontal: {
+ padding: 14,
+ paddingTop: 100,
+ maxHeight: 150,
+ },
+ verticalBox: {
+ flex: 1,
+ minHeight: 500,
+ borderWidth: 5,
+ },
+ horizontalBox: {
+ width: 200,
+ height: "100%",
+ borderWidth: 5,
+ },
+});
diff --git a/example/src/Tests/Screens/index.ts b/example/src/Tests/Screens/index.ts
index 0ed8297004..0816422599 100644
--- a/example/src/Tests/Screens/index.ts
+++ b/example/src/Tests/Screens/index.ts
@@ -4,10 +4,12 @@ import { Snapshot1 } from "./Snapshot1";
import { Snapshot2 } from "./Snapshot2";
import { Snapshot3 } from "./Snapshot3";
import { Snapshot4 } from "./Snapshot4";
+import { Snapshot5 } from "./Snapshot5";
export const Screens: Record = {
Snapshot1,
Snapshot2,
Snapshot3,
Snapshot4,
+ Snapshot5,
};
diff --git a/fabricexample/src/Tests/Screens/Snapshot5.tsx b/fabricexample/src/Tests/Screens/Snapshot5.tsx
new file mode 100644
index 0000000000..1218a0dfa1
--- /dev/null
+++ b/fabricexample/src/Tests/Screens/Snapshot5.tsx
@@ -0,0 +1,68 @@
+import React from "react";
+import { ScrollView, StyleSheet, View } from "react-native";
+
+export const Snapshot5 = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+const Component = () => {
+ return (
+ <>
+ {
+ ref?.scrollTo({ y: 200 });
+ }}
+ >
+
+
+
+
+
+ {
+ ref?.scrollTo({ x: 200 });
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+
+const styles = StyleSheet.create({
+ view: {
+ flex: 1,
+ backgroundColor: "yellow",
+ },
+ scrollview: {
+ padding: 14,
+ paddingTop: 100,
+ maxHeight: 150,
+ },
+ scrollViewHorizontal: {
+ padding: 14,
+ paddingTop: 100,
+ maxHeight: 150,
+ },
+ verticalBox: {
+ flex: 1,
+ minHeight: 500,
+ borderWidth: 5,
+ },
+ horizontalBox: {
+ width: 200,
+ height: "100%",
+ borderWidth: 5,
+ },
+});
diff --git a/fabricexample/src/Tests/Screens/index.ts b/fabricexample/src/Tests/Screens/index.ts
index 0ed8297004..0816422599 100644
--- a/fabricexample/src/Tests/Screens/index.ts
+++ b/fabricexample/src/Tests/Screens/index.ts
@@ -4,10 +4,12 @@ import { Snapshot1 } from "./Snapshot1";
import { Snapshot2 } from "./Snapshot2";
import { Snapshot3 } from "./Snapshot3";
import { Snapshot4 } from "./Snapshot4";
+import { Snapshot5 } from "./Snapshot5";
export const Screens: Record = {
Snapshot1,
Snapshot2,
Snapshot3,
Snapshot4,
+ Snapshot5,
};
diff --git a/package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java b/package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java
index 0bb35280dc..4e63277f26 100644
--- a/package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java
+++ b/package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java
@@ -14,6 +14,7 @@
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ScrollView;
import androidx.annotation.NonNull;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.UIManagerModule;
@@ -70,6 +71,17 @@ private static void renderViewToCanvas(Canvas canvas, View view, Paint paint, fl
canvas.save();
applyTransformations(canvas, view);
+ // If the view is a ScrollView or similar, clip to its bounds
+ if (view instanceof ScrollView) {
+ ScrollView scrollView = (ScrollView) view;
+ int clipLeft = scrollView.getScrollX();
+ int clipTop = scrollView.getScrollY();
+ int clipRight = clipLeft + scrollView.getWidth();
+ int clipBottom = clipTop + scrollView.getHeight();
+
+ canvas.clipRect(clipLeft, clipTop, clipRight, clipBottom);
+ }
+
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
drawBackgroundIfPresent(canvas, view, combinedOpacity);
@@ -166,7 +178,10 @@ private static void drawSurfaceView(Canvas canvas, SurfaceView sv, Paint paint,
private static void applyTransformations(final Canvas c, @NonNull final View view) {
final Matrix matrix = view.getMatrix();
final Matrix translateMatrix = new Matrix();
- translateMatrix.setTranslate(view.getLeft() + view.getPaddingLeft(), view.getTop() + view.getPaddingTop());
+
+ translateMatrix.setTranslate(view.getLeft() + view.getPaddingLeft() - view.getScrollX(),
+ view.getTop() + view.getPaddingTop() - view.getScrollY());
+
c.concat(translateMatrix);
c.concat(matrix);
}
diff --git a/package/src/__tests__/snapshots/screens/snapshot5-android.png b/package/src/__tests__/snapshots/screens/snapshot5-android.png
new file mode 100644
index 0000000000..8b1a1d0b95
Binary files /dev/null and b/package/src/__tests__/snapshots/screens/snapshot5-android.png differ
diff --git a/package/src/renderer/__tests__/e2e/Snapshot.spec.tsx b/package/src/renderer/__tests__/e2e/Snapshot.spec.tsx
index bc3d79daf9..9e29d27009 100644
--- a/package/src/renderer/__tests__/e2e/Snapshot.spec.tsx
+++ b/package/src/renderer/__tests__/e2e/Snapshot.spec.tsx
@@ -24,4 +24,7 @@ describe("Snapshot", () => {
itRunsE2eOnly("should respect overflow: hidden", async () => {
await testSnapshot("Snapshot4");
});
+ itRunsE2eOnly("should respect ScrollView offset and padding", async () => {
+ await testSnapshot("Snapshot5");
+ });
});