diff --git a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js index 9e31118b570d..8a6491576623 100644 --- a/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js +++ b/packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js @@ -11,7 +11,13 @@ 'use strict'; import processBackgroundImage from '../processBackgroundImage'; - +const {OS} = require('../../Utilities/Platform'); +const PlatformColorAndroid = + require('../PlatformColorValueTypes.android').PlatformColor; +const PlatformColorIOS = + require('../PlatformColorValueTypes.ios').PlatformColor; +const DynamicColorIOS = + require('../PlatformColorValueTypesIOS.ios').DynamicColorIOS; const processColor = require('../processColor').default; describe('processBackgroundImage', () => { @@ -587,4 +593,62 @@ describe('processBackgroundImage', () => { expect(result).toEqual([]); expect(result1).toEqual([]); }); + + describe('iOS', () => { + if (OS === 'ios') { + it('should process iOS PlatformColor colors', () => { + const result = processBackgroundImage([ + { + type: 'linearGradient', + colorStops: [ + {color: PlatformColorIOS('systemRedColor'), positions: ['0%']}, + {color: 'red', positions: ['100%']}, + ], + }, + ]); + expect(result[0].colorStops[0].color).toEqual({ + semantic: ['systemRedColor'], + }); + }); + it('should process iOS Dynamic colors', () => { + const result = processBackgroundImage([ + { + type: 'linearGradient', + colorStops: [ + { + color: DynamicColorIOS({light: 'black', dark: 'white'}), + positions: ['0%'], + }, + {color: 'red', positions: ['100%']}, + ], + }, + ]); + expect(result[0].colorStops[0].color).toEqual({ + dynamic: {light: 0xff000000, dark: 0xffffffff}, + }); + }); + } + }); + + describe('Android', () => { + if (OS === 'android') { + it('should process Android PlatformColor colors', () => { + const result = processBackgroundImage([ + { + type: 'linearGradient', + colorStops: [ + { + color: PlatformColorAndroid('?attr/colorPrimary'), + positions: ['0%'], + }, + {color: 'red', positions: ['100%']}, + ], + }, + ]); + expect(result[0].colorStops[0].color).toEqual({ + resource_paths: ['?attr/colorPrimary'], + }); + }); + } + }); }); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BackgroundImageLayer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BackgroundImageLayer.kt index a1f41c2de735..2b8242dfba30 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BackgroundImageLayer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BackgroundImageLayer.kt @@ -7,15 +7,16 @@ package com.facebook.react.uimanager.style +import android.content.Context import android.graphics.Rect import android.graphics.Shader import com.facebook.react.bridge.ReadableMap -public class BackgroundImageLayer(gradientMap: ReadableMap?) { +public class BackgroundImageLayer(gradientMap: ReadableMap?, context: Context) { private val gradient: Gradient? = if (gradientMap != null) { try { - Gradient(gradientMap) + Gradient(gradientMap, context) } catch (e: IllegalArgumentException) { // Gracefully reject invalid styles null diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/Gradient.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/Gradient.kt index 14d027924315..3e99ee2f085e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/Gradient.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/Gradient.kt @@ -7,12 +7,15 @@ package com.facebook.react.uimanager.style +import android.content.Context import android.graphics.LinearGradient import android.graphics.Rect import android.graphics.Shader +import com.facebook.react.bridge.ColorPropConverter import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.ReadableType -public class Gradient(gradient: ReadableMap?) { +public class Gradient(gradient: ReadableMap?, context: Context) { private enum class GradientType { LINEAR_GRADIENT } @@ -55,7 +58,11 @@ public class Gradient(gradient: ReadableMap?) { for (i in 0 until size) { val colorStop = colorStops.getMap(i) - colors[i] = colorStop.getInt("color") + if (colorStop.getType("color") == ReadableType.Map) { + colors[i] = ColorPropConverter.getColor(colorStop.getMap("color"), context); + } else { + colors[i] = colorStop.getInt("color"); + } positions[i] = colorStop.getDouble("position").toFloat() } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index 0ddf094171cf..bac4546af4ee 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -107,7 +107,7 @@ public void setBackgroundImage(ReactViewGroup view, @Nullable ReadableArray back List backgroundImageLayers = new ArrayList<>(backgroundImage.size()); for (int i = 0; i < backgroundImage.size(); i++) { ReadableMap backgroundImageMap = backgroundImage.getMap(i); - BackgroundImageLayer layer = new BackgroundImageLayer(backgroundImageMap); + BackgroundImageLayer layer = new BackgroundImageLayer(backgroundImageMap, view.getContext()); backgroundImageLayers.add(layer); } view.setBackgroundImage(backgroundImageLayers); diff --git a/packages/rn-tester/js/examples/LinearGradient/LinearGradientExample.js b/packages/rn-tester/js/examples/LinearGradient/LinearGradientExample.js index add517122311..6d9bfd857e9d 100644 --- a/packages/rn-tester/js/examples/LinearGradient/LinearGradientExample.js +++ b/packages/rn-tester/js/examples/LinearGradient/LinearGradientExample.js @@ -13,7 +13,7 @@ import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet'; import React from 'react'; -import {StyleSheet, Text, View} from 'react-native'; +import {Platform, PlatformColor, StyleSheet, Text, View} from 'react-native'; type Props = $ReadOnly<{ style: ViewStyleProp, @@ -157,4 +157,33 @@ exports.examples = [ ); }, }, + { + title: 'Gradient with Platform colors', + render(): React.Node { + return ( + + ); + }, + }, ];