mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add mix-blend-mode effects to Android (#45053)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/45053 Add support for most keyword values of mix-blend-mode on Android Missing compositing operators and global values Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D58752052 fbshipit-source-id: e63e01d45a7e0924f3853f08dff5cec7e2f1ceaf
This commit is contained in:
committed by
Facebook GitHub Bot
parent
70bacfe098
commit
ec95533609
@@ -4003,6 +4003,7 @@ public abstract class com/facebook/react/uimanager/BaseViewManager : com/faceboo
|
||||
public fun setElevation (Landroid/view/View;F)V
|
||||
public fun setFilter (Landroid/view/View;Lcom/facebook/react/bridge/ReadableArray;)V
|
||||
public fun setImportantForAccessibility (Landroid/view/View;Ljava/lang/String;)V
|
||||
public fun setMixBlendMode (Landroid/view/View;Ljava/lang/String;)V
|
||||
public fun setMoveShouldSetResponder (Landroid/view/View;Z)V
|
||||
public fun setMoveShouldSetResponderCapture (Landroid/view/View;Z)V
|
||||
public fun setNativeId (Landroid/view/View;Ljava/lang/String;)V
|
||||
@@ -4073,6 +4074,7 @@ public abstract interface class com/facebook/react/uimanager/BaseViewManagerInte
|
||||
public abstract fun setElevation (Landroid/view/View;F)V
|
||||
public abstract fun setFilter (Landroid/view/View;Lcom/facebook/react/bridge/ReadableArray;)V
|
||||
public abstract fun setImportantForAccessibility (Landroid/view/View;Ljava/lang/String;)V
|
||||
public abstract fun setMixBlendMode (Landroid/view/View;Ljava/lang/String;)V
|
||||
public abstract fun setNativeId (Landroid/view/View;Ljava/lang/String;)V
|
||||
public abstract fun setOpacity (Landroid/view/View;F)V
|
||||
public abstract fun setRenderToHardwareTexture (Landroid/view/View;Z)V
|
||||
@@ -5449,6 +5451,7 @@ public final class com/facebook/react/uimanager/ViewProps {
|
||||
public static final field MINIMUM_FONT_SCALE Ljava/lang/String;
|
||||
public static final field MIN_HEIGHT Ljava/lang/String;
|
||||
public static final field MIN_WIDTH Ljava/lang/String;
|
||||
public static final field MIX_BLEND_MODE Ljava/lang/String;
|
||||
public static final field NATIVE_ID Ljava/lang/String;
|
||||
public static final field NEEDS_OFFSCREEN_ALPHA_COMPOSITING Ljava/lang/String;
|
||||
public static final field NONE Ljava/lang/String;
|
||||
|
||||
+39
-19
@@ -7,6 +7,7 @@
|
||||
|
||||
package com.facebook.react.uimanager;
|
||||
|
||||
import android.graphics.BlendMode;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Build;
|
||||
@@ -107,7 +108,7 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
||||
|
||||
view.setTag(R.id.use_hardware_layer, null);
|
||||
view.setTag(R.id.filter, null);
|
||||
applyFilter(view, null);
|
||||
applyLayerEffects(view, null, null, null);
|
||||
|
||||
// setShadowColor
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
@@ -192,6 +193,12 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
||||
view.setTag(R.id.filter, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = ViewProps.MIX_BLEND_MODE)
|
||||
public void setMixBlendMode(@NonNull T view, @Nullable String mixBlendMode) {
|
||||
view.setTag(R.id.mix_blend_mode, BlendModeHelper.parseMixBlendMode(mixBlendMode));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ReactProp(name = ViewProps.TRANSFORM)
|
||||
public void setTransform(@NonNull T view, @Nullable ReadableArray matrix) {
|
||||
@@ -497,25 +504,37 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
||||
}
|
||||
}
|
||||
|
||||
private void applyFilter(@NonNull T view, @Nullable ReadableArray filter) {
|
||||
private void applyLayerEffects(
|
||||
@NonNull T view,
|
||||
@Nullable ReadableArray filter,
|
||||
@Nullable BlendMode mixBlendMode,
|
||||
@Nullable Boolean useHWLayer) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
view.setRenderEffect(null);
|
||||
}
|
||||
Boolean useHWLayer = (Boolean) view.getTag(R.id.use_hardware_layer);
|
||||
int layerType =
|
||||
useHWLayer != null && useHWLayer ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
|
||||
view.setLayerType(layerType, null);
|
||||
|
||||
if (filter == null) {
|
||||
return;
|
||||
@Nullable Paint p = null;
|
||||
|
||||
if (filter != null) {
|
||||
if (FilterHelper.isOnlyColorMatrixFilters(filter)) {
|
||||
p = new Paint();
|
||||
p.setColorFilter(FilterHelper.parseColorMatrixFilters(filter));
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
view.setRenderEffect(FilterHelper.parseFilters(filter));
|
||||
}
|
||||
}
|
||||
|
||||
if (FilterHelper.isOnlyColorMatrixFilters(filter)) {
|
||||
Paint p = new Paint();
|
||||
p.setColorFilter(FilterHelper.parseColorMatrixFilters(filter));
|
||||
if (mixBlendMode != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
p = p == null ? new Paint() : p;
|
||||
p.setBlendMode(mixBlendMode);
|
||||
}
|
||||
|
||||
if (p == null) {
|
||||
int layerType =
|
||||
useHWLayer != null && useHWLayer ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
|
||||
view.setLayerType(layerType, null);
|
||||
} else {
|
||||
view.setLayerType(View.LAYER_TYPE_HARDWARE, p);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
view.setRenderEffect(FilterHelper.parseFilters(filter));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,13 +644,14 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
||||
view.setTag(R.id.invalidate_transform, false);
|
||||
}
|
||||
|
||||
Boolean useHWLayer = (Boolean) view.getTag(R.id.use_hardware_layer);
|
||||
if (useHWLayer != null) {
|
||||
view.setLayerType(useHWLayer ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE, null);
|
||||
}
|
||||
|
||||
ReadableArray filter = (ReadableArray) view.getTag(R.id.filter);
|
||||
applyFilter(view, filter);
|
||||
BlendMode mixBlendMode =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
||||
? (BlendMode) view.getTag(R.id.mix_blend_mode)
|
||||
: null;
|
||||
Boolean useHWLayer = (Boolean) view.getTag(R.id.use_hardware_layer);
|
||||
|
||||
applyLayerEffects(view, filter, mixBlendMode, useHWLayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
@@ -50,6 +50,8 @@ public interface BaseViewManagerInterface<T extends View> {
|
||||
|
||||
void setFilter(T view, ReadableArray filter);
|
||||
|
||||
void setMixBlendMode(T view, String setMixBlendMode);
|
||||
|
||||
void setShadowColor(T view, int shadowColor);
|
||||
|
||||
void setImportantForAccessibility(T view, @Nullable String importantForAccessibility);
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.uimanager
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.graphics.BlendMode
|
||||
|
||||
@TargetApi(29)
|
||||
internal object BlendModeHelper {
|
||||
|
||||
/** @see https://www.w3.org/TR/compositing-1/#mix-blend-mode */
|
||||
@JvmStatic
|
||||
public fun parseMixBlendMode(mixBlendMode: String?): BlendMode? {
|
||||
mixBlendMode ?: return null
|
||||
|
||||
return when (mixBlendMode) {
|
||||
"normal" -> null
|
||||
"multiply" -> BlendMode.MULTIPLY
|
||||
"screen" -> BlendMode.SCREEN
|
||||
"overlay" -> BlendMode.OVERLAY
|
||||
"darken" -> BlendMode.DARKEN
|
||||
"lighten" -> BlendMode.LIGHTEN
|
||||
"color-dodge" -> BlendMode.COLOR_DODGE
|
||||
"color-burn" -> BlendMode.COLOR_BURN
|
||||
"hard-light" -> BlendMode.HARD_LIGHT
|
||||
"soft-light" -> BlendMode.SOFT_LIGHT
|
||||
"difference" -> BlendMode.DIFFERENCE
|
||||
"exclusion" -> BlendMode.EXCLUSION
|
||||
"hue" -> BlendMode.HUE
|
||||
"saturation" -> BlendMode.SATURATION
|
||||
"color" -> BlendMode.COLOR
|
||||
"luminosity" -> BlendMode.LUMINOSITY
|
||||
else -> throw IllegalArgumentException("Invalid mix-blend-mode name: $mixBlendMode")
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -136,6 +136,7 @@ public object ViewProps {
|
||||
public const val BORDER_END_COLOR: String = "borderEndColor"
|
||||
public const val ON_LAYOUT: String = "onLayout"
|
||||
public const val FILTER: String = "experimental_filter"
|
||||
public const val MIX_BLEND_MODE: String = "experimental_mixBlendMode"
|
||||
public const val TRANSFORM: String = "transform"
|
||||
public const val TRANSFORM_ORIGIN: String = "transformOrigin"
|
||||
public const val ELEVATION: String = "elevation"
|
||||
|
||||
@@ -62,4 +62,7 @@
|
||||
|
||||
<!-- tag is used to store graphical filter effects to apply to the view -->
|
||||
<item type="id" name="filter"/>
|
||||
|
||||
<!-- tag is used to store mixBlendMode effects to apply to the view -->
|
||||
<item type="id" name="mix_blend_mode"/>
|
||||
</resources>
|
||||
|
||||
@@ -166,6 +166,15 @@ BaseViewProps::BaseViewProps(
|
||||
"experimental_filter",
|
||||
sourceProps.filter,
|
||||
{})),
|
||||
mixBlendMode(
|
||||
CoreFeatures::enablePropIteratorSetter
|
||||
? sourceProps.mixBlendMode
|
||||
: convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"experimental_mixBlendMode",
|
||||
sourceProps.mixBlendMode,
|
||||
{})),
|
||||
transform(
|
||||
CoreFeatures::enablePropIteratorSetter ? sourceProps.transform
|
||||
: convertRawProp(
|
||||
|
||||
@@ -62,6 +62,9 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps {
|
||||
// Filter
|
||||
std::vector<FilterPrimitive> filter{};
|
||||
|
||||
// MixBlendMode
|
||||
std::string mixBlendMode;
|
||||
|
||||
// Transform
|
||||
Transform transform{};
|
||||
TransformOrigin transformOrigin{
|
||||
|
||||
@@ -61,7 +61,7 @@ void ViewShadowNode::initialize() noexcept {
|
||||
viewProps.accessibilityViewIsModal ||
|
||||
viewProps.importantForAccessibility != ImportantForAccessibility::Auto ||
|
||||
viewProps.removeClippedSubviews || viewProps.cursor != Cursor::Auto ||
|
||||
!viewProps.filter.empty() ||
|
||||
!viewProps.filter.empty() || !viewProps.mixBlendMode.empty() ||
|
||||
HostPlatformViewTraitsInitializer::formsStackingContext(viewProps);
|
||||
|
||||
bool formsView = formsStackingContext ||
|
||||
|
||||
Reference in New Issue
Block a user