Skip to content

Commit 24b0ded

Browse files
jorge-cabfacebook-github-bot
authored andcommitted
Enable mix-blend-mode on ReactRootView so blending works with app background (facebook#47336)
Summary: Pull Request resolved: facebook#47336 Before mix-blend-mode would not blend with the background color due to it not being a ViewGroup. This adds the mix-blend-mode logic to ReactRootView so blending works Changelog: [Android][Fixed] - Enable mix-blend-mode on ReactRootView so blending works with app background Reviewed By: NickGerleman Differential Revision: D65156543 fbshipit-source-id: b3628b667573d0b56c74214e40d21c656fda495a
1 parent 30e75a5 commit 24b0ded

File tree

4 files changed

+41
-13
lines changed

4 files changed

+41
-13
lines changed

packages/react-native/ReactAndroid/api/ReactAndroid.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ public class com/facebook/react/ReactRootView : android/widget/FrameLayout, com/
377377
protected fun dispatchJSPointerEvent (Landroid/view/MotionEvent;Z)V
378378
protected fun dispatchJSTouchEvent (Landroid/view/MotionEvent;)V
379379
public fun dispatchKeyEvent (Landroid/view/KeyEvent;)Z
380+
protected fun drawChild (Landroid/graphics/Canvas;Landroid/view/View;J)Z
380381
protected fun finalize ()V
381382
public fun getAppProperties ()Landroid/os/Bundle;
382383
public fun getCurrentReactContext ()Lcom/facebook/react/bridge/ReactContext;

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
package com.facebook.react;
99

1010
import static com.facebook.infer.annotation.ThreadConfined.UI;
11+
import static com.facebook.react.uimanager.BlendModeHelper.needsIsolatedLayer;
1112
import static com.facebook.react.uimanager.common.UIManagerType.DEFAULT;
1213
import static com.facebook.react.uimanager.common.UIManagerType.FABRIC;
1314
import static com.facebook.systrace.Systrace.TRACE_TAG_REACT_JAVA_BRIDGE;
1415

1516
import android.content.Context;
17+
import android.graphics.BlendMode;
1618
import android.graphics.Canvas;
1719
import android.graphics.Insets;
20+
import android.graphics.Paint;
1821
import android.graphics.Point;
1922
import android.graphics.Rect;
2023
import android.os.Build;
@@ -65,6 +68,7 @@
6568
import com.facebook.react.uimanager.RootViewUtil;
6669
import com.facebook.react.uimanager.UIManagerHelper;
6770
import com.facebook.react.uimanager.common.UIManagerType;
71+
import com.facebook.react.uimanager.common.ViewUtil;
6872
import com.facebook.react.uimanager.events.EventDispatcher;
6973
import com.facebook.systrace.Systrace;
7074
import java.util.concurrent.atomic.AtomicInteger;
@@ -290,6 +294,30 @@ protected void dispatchDraw(Canvas canvas) {
290294
}
291295
}
292296

297+
@Override
298+
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
299+
300+
BlendMode mixBlendMode = null;
301+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
302+
&& ViewUtil.getUIManagerType(this) == UIManagerType.FABRIC
303+
&& needsIsolatedLayer(this)) {
304+
mixBlendMode = (BlendMode) child.getTag(R.id.mix_blend_mode);
305+
if (mixBlendMode != null) {
306+
Paint p = new Paint();
307+
p.setBlendMode(mixBlendMode);
308+
canvas.saveLayer(0, 0, getWidth(), getHeight(), p);
309+
}
310+
}
311+
312+
boolean result = super.drawChild(canvas, child, drawingTime);
313+
314+
if (mixBlendMode != null) {
315+
canvas.restore();
316+
}
317+
318+
return result;
319+
}
320+
293321
@Override
294322
public boolean dispatchKeyEvent(KeyEvent ev) {
295323
if (!hasActiveReactContext() || !isViewAttachedToReactInstance()) {

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/BlendModeHelper.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ package com.facebook.react.uimanager
1010
import android.annotation.TargetApi
1111
import android.graphics.BlendMode
1212
import android.os.Build
13+
import android.view.ViewGroup
14+
import androidx.core.view.children
15+
import com.facebook.react.R
1316

1417
@TargetApi(29)
1518
internal object BlendModeHelper {
@@ -41,4 +44,8 @@ internal object BlendModeHelper {
4144
else -> throw IllegalArgumentException("Invalid mix-blend-mode name: $mixBlendMode")
4245
}
4346
}
47+
48+
@JvmStatic
49+
public fun needsIsolatedLayer(view: ViewGroup): Boolean =
50+
view.children.any { it.getTag(R.id.mix_blend_mode) != null }
4451
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.facebook.react.touch.ReactHitSlopView;
3838
import com.facebook.react.touch.ReactInterceptingViewGroup;
3939
import com.facebook.react.uimanager.BackgroundStyleApplicator;
40+
import com.facebook.react.uimanager.BlendModeHelper;
4041
import com.facebook.react.uimanager.LengthPercentage;
4142
import com.facebook.react.uimanager.LengthPercentageType;
4243
import com.facebook.react.uimanager.MeasureSpecAssertions;
@@ -747,16 +748,6 @@ private void removeFromArray(int index) {
747748
}
748749
}
749750

750-
private boolean needsIsolatedLayer() {
751-
for (int i = 0; i < getChildCount(); i++) {
752-
if (getChildAt(i).getTag(R.id.mix_blend_mode) != null) {
753-
return true;
754-
}
755-
}
756-
757-
return false;
758-
}
759-
760751
@Override
761752
public @Nullable Rect getHitSlopRect() {
762753
return mHitSlopRect;
@@ -793,7 +784,7 @@ public void setOverflow(@Nullable String overflow) {
793784

794785
@Override
795786
public void setOverflowInset(int left, int top, int right, int bottom) {
796-
if (needsIsolatedLayer()
787+
if (BlendModeHelper.needsIsolatedLayer(this)
797788
&& (mOverflowInset.left != left
798789
|| mOverflowInset.top != top
799790
|| mOverflowInset.right != right
@@ -823,7 +814,7 @@ public Rect getOverflowInset() {
823814
public void draw(Canvas canvas) {
824815
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
825816
&& ViewUtil.getUIManagerType(this) == UIManagerType.FABRIC
826-
&& needsIsolatedLayer()) {
817+
&& BlendModeHelper.needsIsolatedLayer(this)) {
827818

828819
// Check if the view is a stacking context and has children, if it does, do the rendering
829820
// offscreen and then composite back. This follows the idea of group isolation on blending
@@ -859,7 +850,8 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
859850
}
860851

861852
BlendMode mixBlendMode = null;
862-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && needsIsolatedLayer()) {
853+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
854+
&& BlendModeHelper.needsIsolatedLayer(this)) {
863855
mixBlendMode = (BlendMode) child.getTag(R.id.mix_blend_mode);
864856
if (mixBlendMode != null) {
865857
Paint p = new Paint();

0 commit comments

Comments
 (0)