diff --git a/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js b/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js
index 0a73eb53c847..b69b350e99e4 100644
--- a/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js
+++ b/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js
@@ -159,6 +159,7 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
*/
color: colorAttributes,
fontFamily: true,
+ fontVariationSettings: true,
fontSize: true,
fontStyle: true,
fontVariant: {process: processFontVariant},
diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts
index 9ef13a7bd74f..82ba6ecec7cf 100644
--- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts
+++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts
@@ -330,6 +330,7 @@ export interface TextStyleAndroid extends ViewStyle {
export interface TextStyle extends TextStyleIOS, TextStyleAndroid, ViewStyle {
color?: ColorValue | undefined;
fontFamily?: string | undefined;
+ fontVariationSettings?: string | undefined;
fontSize?: number | undefined;
fontStyle?: 'normal' | 'italic' | undefined;
/**
diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js
index de54f8235f5e..ce69e28e1244 100644
--- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js
+++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js
@@ -834,6 +834,7 @@ export type ____TextStyle_InternalCore = $ReadOnly<{
...$Exact<____ViewStyle_Internal>,
color?: ____ColorValue_Internal,
fontFamily?: string,
+ fontVariationSettings?: string,
fontSize?: number,
fontStyle?: 'normal' | 'italic',
fontWeight?: ____FontWeight_Internal,
diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap
index 58e73cf5d904..1da8f7b145b1 100644
--- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap
+++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap
@@ -7819,6 +7819,7 @@ export type ____TextStyle_InternalCore = $ReadOnly<{
...$Exact<____ViewStyle_Internal>,
color?: ____ColorValue_Internal,
fontFamily?: string,
+ fontVariationSettings?: string,
fontSize?: number,
fontStyle?: \\"normal\\" | \\"italic\\",
fontWeight?: ____FontWeight_Internal,
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt
index 5b6c2bef0d6d..257a1a60b984 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.kt
@@ -81,6 +81,7 @@ public object ViewProps {
public const val FONT_STYLE: String = "fontStyle"
public const val FONT_VARIANT: String = "fontVariant"
public const val FONT_FAMILY: String = "fontFamily"
+ public const val FONT_VARIATION_SETTINGS: String = "fontVariationSettings";
public const val LINE_HEIGHT: String = "lineHeight"
public const val LETTER_SPACING: String = "letterSpacing"
public const val NEEDS_OFFSCREEN_ALPHA_COMPOSITING: String = "needsOffscreenAlphaCompositing"
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java
index 6cb16d00028d..3fe093549c0c 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactBaseTextShadowNode.java
@@ -193,6 +193,7 @@ private static void buildSpannedFromShadowNode(
}
if (textShadowNode.mFontStyle != ReactConstants.UNSET
|| textShadowNode.mFontWeight != ReactConstants.UNSET
+ || textShadowNode.mFontVariationSettings != null
|| textShadowNode.mFontFamily != null) {
ops.add(
new SetSpanOperation(
@@ -203,6 +204,7 @@ private static void buildSpannedFromShadowNode(
textShadowNode.mFontWeight,
textShadowNode.mFontFeatureSettings,
textShadowNode.mFontFamily,
+ textShadowNode.mFontVariationSettings,
textShadowNode.getThemedContext().getAssets())));
}
if (textShadowNode.mIsUnderlineTextDecorationSet) {
@@ -348,6 +350,11 @@ protected Spannable spannedFromShadowNode(
protected int mFontWeight = ReactConstants.UNSET;
+ /**
+ * mFontVariationSettings can be used for variable font features e.g: 'wght' 850
+ */
+ protected String mFontVariationSettings;
+
/**
* NB: If a font family is used that does not have a style in a certain Android version (ie.
* monospace bold pre Android 5.0), that style (ie. bold) will not be inherited by nested Text
@@ -525,6 +532,12 @@ public void setFontWeight(@Nullable String fontWeightString) {
}
}
+ @ReactProp(name = ViewProps.FONT_VARIATION_SETTINGS)
+ public void setFontVariationSettings(@Nullable String fontVariationSettings) {
+ mFontVariationSettings = fontVariationSettings;
+ markUpdated();
+ }
+
@ReactProp(name = ViewProps.FONT_VARIANT)
public void setFontVariant(@Nullable ReadableArray fontVariantArray) {
String fontFeatureSettings = ReactTypefaceUtils.parseFontVariant(fontVariantArray);
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java
index f5dc16e69bd8..1fadf7780cc5 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java
@@ -61,6 +61,8 @@ public class TextAttributeProps {
public static final short TA_KEY_LINE_BREAK_STRATEGY = 25;
public static final short TA_KEY_ROLE = 26;
public static final short TA_KEY_TEXT_TRANSFORM = 27;
+ public static final short TA_KEY_ALIGNMENT_VERTICAL = 28;
+ public static final short TA_KEY_FONT_VARIATION_SETTINGS = 29;
public static final int UNSET = -1;
@@ -135,6 +137,12 @@ public class TextAttributeProps {
*/
protected @Nullable String mFontFamily = null;
+ /**
+ * mFontVariationSettings can be used for variable font features e.g: 'wght' 850
+ * This works for Android 8.1 and above.
+ */
+ protected @Nullable String mFontVariationSettings = null;
+
/**
* @see android.graphics.Paint#setFontFeatureSettings
*/
@@ -225,6 +233,9 @@ public static TextAttributeProps fromMapBuffer(MapBuffer props) {
case TA_KEY_TEXT_TRANSFORM:
result.setTextTransform(entry.getStringValue());
break;
+ case TA_KEY_FONT_VARIATION_SETTINGS:
+ result.setFontVariationSettings(entry.getStringValue());
+ break;
}
}
@@ -252,6 +263,7 @@ public static TextAttributeProps fromReadableMap(ReactStylesDiffMap props) {
? props.getInt(ViewProps.BACKGROUND_COLOR, 0)
: null);
result.setFontFamily(getStringProp(props, ViewProps.FONT_FAMILY));
+ result.setFontVariationSettings(getStringProp(props, ViewProps.FONT_VARIATION_SETTINGS));
result.setFontWeight(getStringProp(props, ViewProps.FONT_WEIGHT));
result.setFontStyle(getStringProp(props, ViewProps.FONT_STYLE));
result.setFontVariant(getArrayProp(props, ViewProps.FONT_VARIANT));
@@ -465,10 +477,18 @@ public String getFontFamily() {
return mFontFamily;
}
+ public String getFontVariationSettings() {
+ return mFontVariationSettings;
+ }
+
private void setFontFamily(@Nullable String fontFamily) {
mFontFamily = fontFamily;
}
+ private void setFontVariationSettings(String fontVariationSettings) {
+ mFontVariationSettings = fontVariationSettings;
+ }
+
private void setFontVariant(@Nullable ReadableArray fontVariant) {
mFontFeatureSettings = ReactTypefaceUtils.parseFontVariant(fontVariant);
}
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java
index 2921f84140d1..0f8585a3137f 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextLayoutManager.java
@@ -249,6 +249,7 @@ private static void buildSpannableFromFragments(
new SetSpanOperation(start, end, new ReactAbsoluteSizeSpan(textAttributes.mFontSize)));
if (textAttributes.mFontStyle != ReactConstants.UNSET
|| textAttributes.mFontWeight != ReactConstants.UNSET
+ || textAttributes.mFontVariationSettings != null
|| textAttributes.mFontFamily != null) {
ops.add(
new SetSpanOperation(
@@ -259,6 +260,7 @@ private static void buildSpannableFromFragments(
textAttributes.mFontWeight,
textAttributes.mFontFeatureSettings,
textAttributes.mFontFamily,
+ textAttributes.mFontVariationSettings,
context.getAssets())));
}
if (textAttributes.mIsUnderlineTextDecorationSet) {
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt
index 81bb303e6a30..738e9ff5bd04 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/internal/span/CustomStyleSpan.kt
@@ -10,6 +10,7 @@ package com.facebook.react.views.text.internal.span
import android.content.res.AssetManager
import android.graphics.Paint
import android.graphics.Typeface
+import android.os.Build
import android.text.TextPaint
import android.text.style.MetricAffectingSpan
import com.facebook.react.common.ReactConstants
@@ -32,14 +33,15 @@ public class CustomStyleSpan(
private val privateWeight: Int,
public val fontFeatureSettings: String?,
public val fontFamily: String?,
+ public val fontVariationSettings: String?,
private val assetManager: AssetManager
) : MetricAffectingSpan(), ReactSpan {
public override fun updateDrawState(ds: TextPaint) {
- apply(ds, privateStyle, privateWeight, fontFeatureSettings, fontFamily, assetManager)
+ apply(ds, privateStyle, privateWeight, fontFeatureSettings, fontFamily, fontVariationSettings, assetManager)
}
public override fun updateMeasureState(paint: TextPaint) {
- apply(paint, privateStyle, privateWeight, fontFeatureSettings, fontFamily, assetManager)
+ apply(paint, privateStyle, privateWeight, fontFeatureSettings, fontFamily, fontVariationSettings, assetManager)
}
public val style: Int
@@ -59,12 +61,14 @@ public class CustomStyleSpan(
}
public companion object {
+ private val TAG = CustomStyleSpan::class.simpleName
private fun apply(
paint: Paint,
style: Int,
weight: Int,
fontFeatureSettingsParam: String?,
family: String?,
+ fontVariationSettingsParam: String?,
assetManager: AssetManager
) {
val typeface =
@@ -72,6 +76,13 @@ public class CustomStyleSpan(
paint.apply {
fontFeatureSettings = fontFeatureSettingsParam
setTypeface(typeface)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ try {
+ fontVariationSettings = fontVariationSettingsParam
+ } catch (e: IllegalArgumentException) {
+ // Do nothing
+ }
+ }
isSubpixelText = true
}
}
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java
index 014e0b489dd3..e7da1b969ab1 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java
@@ -39,6 +39,8 @@
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
+import android.widget.TextView;
+
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatEditText;
import androidx.core.util.Predicate;
@@ -527,7 +529,7 @@ public void setInputType(int type) {
/**
* If set forces multiline on input, because of a restriction on Android source that enables
* multiline only for inputs of type Text and Multiline on method {@link
- * android.widget.TextView#isMultilineInputType(int)}} Source: {@Link TextView.java}
*/
if (isMultiline()) {
@@ -598,6 +600,7 @@ public void maybeUpdateTypeface() {
if (mFontStyle != ReactConstants.UNSET
|| mFontWeight != ReactConstants.UNSET
|| mFontFamily != null
+ || getFontVariationSettingsInternal() != null
|| getFontFeatureSettings() != null) {
setPaintFlags(getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
} else {
@@ -771,10 +774,20 @@ private void stripStyleEquivalentSpans(SpannableStringBuilder sb) {
return span.getStyle() == mFontStyle
&& Objects.equals(span.getFontFamily(), mFontFamily)
&& span.getWeight() == mFontWeight
+ && Objects.equals(span.getFontVariationSettings(), getFontVariationSettingsInternal())
&& Objects.equals(span.getFontFeatureSettings(), getFontFeatureSettings());
});
}
+ // Font variation settings is only available on API 26+, we return null if not available
+ private @Nullable String getFontVariationSettingsInternal() {
+ String fontVariationSettings = null;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ fontVariationSettings = super.getFontVariationSettings();
+ }
+ return fontVariationSettings;
+ }
+
private void stripSpansOfKind(
SpannableStringBuilder sb, Class clazz, Predicate shouldStrip) {
T[] spans = sb.getSpans(0, sb.length(), clazz);
@@ -829,6 +842,7 @@ private void addSpansFromStyleAttributes(SpannableStringBuilder workingText) {
if (mFontStyle != ReactConstants.UNSET
|| mFontWeight != ReactConstants.UNSET
|| mFontFamily != null
+ || getFontVariationSettingsInternal() != null
|| getFontFeatureSettings() != null) {
workingText.setSpan(
new CustomStyleSpan(
@@ -836,6 +850,7 @@ private void addSpansFromStyleAttributes(SpannableStringBuilder workingText) {
mFontWeight,
getFontFeatureSettings(),
mFontFamily,
+ getFontVariationSettingsInternal(),
getContext().getAssets()),
0,
workingText.length(),
diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java
index 2c225da15548..5e936667580f 100644
--- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java
+++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java
@@ -389,6 +389,11 @@ public void setFontFamily(ReactEditText view, String fontFamily) {
view.setFontFamily(fontFamily);
}
+ @ReactProp(name = ViewProps.FONT_VARIATION_SETTINGS)
+ public void setFontVariationSettings(ReactEditText view, String fontVariationSettings) {
+ view.setFontVariationSettings(fontVariationSettings);
+ }
+
@ReactProp(name = ViewProps.MAX_FONT_SIZE_MULTIPLIER, defaultFloat = Float.NaN)
public void setMaxFontSizeMultiplier(ReactEditText view, float maxFontSizeMultiplier) {
view.setMaxFontSizeMultiplier(maxFontSizeMultiplier);
diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp
index cd32048480f5..3a9c8fdb2632 100644
--- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp
@@ -31,6 +31,8 @@ void TextAttributes::apply(TextAttributes textAttributes) {
// Font
fontFamily = !textAttributes.fontFamily.empty() ? textAttributes.fontFamily
: fontFamily;
+ fontVariationSettings = !textAttributes.fontVariationSettings.empty() ? textAttributes.fontVariationSettings
+ : fontVariationSettings;
fontSize =
!std::isnan(textAttributes.fontSize) ? textAttributes.fontSize : fontSize;
fontSizeMultiplier = !std::isnan(textAttributes.fontSizeMultiplier)
@@ -121,6 +123,7 @@ bool TextAttributes::operator==(const TextAttributes& rhs) const {
foregroundColor,
backgroundColor,
fontFamily,
+ fontVariationSettings,
fontWeight,
fontStyle,
fontVariant,
@@ -145,6 +148,7 @@ bool TextAttributes::operator==(const TextAttributes& rhs) const {
rhs.foregroundColor,
rhs.backgroundColor,
rhs.fontFamily,
+ rhs.fontVariationSettings,
rhs.fontWeight,
rhs.fontStyle,
rhs.fontVariant,
@@ -202,6 +206,7 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const {
// Font
debugStringConvertibleItem("fontFamily", fontFamily),
+ debugStringConvertibleItem("fontVariationSettings", fontVariationSettings),
debugStringConvertibleItem("fontSize", fontSize),
debugStringConvertibleItem("fontSizeMultiplier", fontSizeMultiplier),
debugStringConvertibleItem("fontWeight", fontWeight),
diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h
index c8ff0cbd40a4..39b50ec6a979 100644
--- a/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h
+++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/TextAttributes.h
@@ -45,6 +45,7 @@ class TextAttributes : public DebugStringConvertible {
// Font
std::string fontFamily{""};
+ std::string fontVariationSettings{""};
Float fontSize{std::numeric_limits::quiet_NaN()};
Float fontSizeMultiplier{std::numeric_limits::quiet_NaN()};
std::optional fontWeight{};
@@ -115,6 +116,7 @@ struct hash {
textAttributes.backgroundColor,
textAttributes.opacity,
textAttributes.fontFamily,
+ textAttributes.fontVariationSettings,
textAttributes.fontSize,
textAttributes.fontSizeMultiplier,
textAttributes.fontWeight,
diff --git a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h
index a975fe080d9b..8eab9239aa9b 100644
--- a/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h
+++ b/packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h
@@ -856,6 +856,7 @@ constexpr static MapBuffer::Key TA_KEY_LINE_BREAK_STRATEGY = 25;
constexpr static MapBuffer::Key TA_KEY_ROLE = 26;
constexpr static MapBuffer::Key TA_KEY_TEXT_TRANSFORM = 27;
constexpr static MapBuffer::Key TA_KEY_ALIGNMENT_VERTICAL = 28;
+constexpr static MapBuffer::Key TA_KEY_FONT_VARIATION_SETTINGS = 29;
// constants for ParagraphAttributes serialization
constexpr static MapBuffer::Key PA_KEY_MAX_NUMBER_OF_LINES = 0;
@@ -929,6 +930,9 @@ inline MapBuffer toMapBuffer(const TextAttributes& textAttributes) {
if (!textAttributes.fontFamily.empty()) {
builder.putString(TA_KEY_FONT_FAMILY, textAttributes.fontFamily);
}
+ if (!textAttributes.fontVariationSettings.empty()) {
+ builder.putString(TA_KEY_FONT_VARIATION_SETTINGS, textAttributes.fontVariationSettings);
+ }
if (!std::isnan(textAttributes.fontSize)) {
builder.putDouble(TA_KEY_FONT_SIZE, textAttributes.fontSize);
}
diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp
index 2dfe49020d2e..93fe9c6da7d2 100644
--- a/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/components/text/BaseTextProps.cpp
@@ -37,6 +37,12 @@ static TextAttributes convertRawProp(
"fontFamily",
sourceTextAttributes.fontFamily,
defaultTextAttributes.fontFamily);
+ textAttributes.fontVariationSettings = convertRawProp(
+ context,
+ rawProps,
+ "fontVariationSettings",
+ sourceTextAttributes.fontVariationSettings,
+ defaultTextAttributes.fontVariationSettings);
textAttributes.fontSize = convertRawProp(
context,
rawProps,
@@ -244,6 +250,8 @@ void BaseTextProps::setProp(
defaults, value, textAttributes, foregroundColor, "color");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, fontFamily, "fontFamily");
+ REBUILD_FIELD_SWITCH_CASE(
+ defaults, value, textAttributes, fontVariationSettings, "fontVariationSettings");
REBUILD_FIELD_SWITCH_CASE(
defaults, value, textAttributes, fontSize, "fontSize");
REBUILD_FIELD_SWITCH_CASE(
diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp
index 6f318ca70956..31e248c27a4c 100644
--- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp
+++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp
@@ -165,6 +165,8 @@ AndroidTextInputProps::AndroidTextInputProps(
convertRawProp(context, rawProps, "fontWeight", sourceProps.fontWeight, {})),
fontFamily(CoreFeatures::enablePropIteratorSetter? sourceProps.fontFamily :
convertRawProp(context, rawProps, "fontFamily", sourceProps.fontFamily, {})),
+ fontVariationSettings(CoreFeatures::enablePropIteratorSetter? sourceProps.fontVariationSettings :
+ convertRawProp(context, rawProps, "fontVariationSettings", sourceProps.fontVariationSettings, {})),
// See AndroidTextInputComponentDescriptor for usage
// TODO T63008435: can these, and this feature, be removed entirely?
hasPadding(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPadding : hasValue(rawProps, sourceProps.hasPadding, "padding")),
@@ -246,6 +248,7 @@ void AndroidTextInputProps::setProp(
RAW_SET_PROP_SWITCH_CASE_BASIC(includeFontPadding);
RAW_SET_PROP_SWITCH_CASE_BASIC(fontWeight);
RAW_SET_PROP_SWITCH_CASE_BASIC(fontFamily);
+ RAW_SET_PROP_SWITCH_CASE_BASIC(fontVariationSettings);
case CONSTEXPR_RAW_PROPS_KEY_HASH("value"): {
fromRawValue(context, value, this->value, {});
@@ -343,6 +346,7 @@ folly::dynamic AndroidTextInputProps::getDynamic() const {
props["includeFontPadding"] = includeFontPadding;
props["fontWeight"] = fontWeight;
props["fontFamily"] = fontFamily;
+ props["fontVariationSettings"] = fontVariationSettings;
props["cursorColor"] = toAndroidRepr(cursorColor);
props["mostRecentEventCount"] = mostRecentEventCount;
props["text"] = text;
diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h
index da41bb4ce251..f8459a91f4a5 100644
--- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h
+++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h
@@ -111,6 +111,7 @@ class AndroidTextInputProps final : public BaseTextInputProps {
bool includeFontPadding{false};
std::string fontWeight{};
std::string fontFamily{};
+ std::string fontVariationSettings{};
/**
* Auxiliary information to detect if these props are set or not.
diff --git a/packages/rn-tester/android/app/src/main/assets/fonts/MaterialSymbolsSharp.ttf b/packages/rn-tester/android/app/src/main/assets/fonts/MaterialSymbolsSharp.ttf
new file mode 100644
index 000000000000..a0ab3cfc537e
Binary files /dev/null and b/packages/rn-tester/android/app/src/main/assets/fonts/MaterialSymbolsSharp.ttf differ
diff --git a/packages/rn-tester/android/app/src/main/assets/fonts/inter.ttf b/packages/rn-tester/android/app/src/main/assets/fonts/inter.ttf
new file mode 100644
index 000000000000..e72470871b8f
Binary files /dev/null and b/packages/rn-tester/android/app/src/main/assets/fonts/inter.ttf differ
diff --git a/packages/rn-tester/js/examples/Text/TextExample.android.js b/packages/rn-tester/js/examples/Text/TextExample.android.js
index c8acafe10e96..76c66799d600 100644
--- a/packages/rn-tester/js/examples/Text/TextExample.android.js
+++ b/packages/rn-tester/js/examples/Text/TextExample.android.js
@@ -506,6 +506,76 @@ function FontWeightExample(props: {}): React.Node {
);
}
+function FontVariationSettingsExample(props: {}): React.Node {
+ const fontSettings = [
+ "'wght' 100",
+ "'wght' 200",
+ "'wght' 300",
+ "'wght' 400",
+ "'wght' 500",
+ "'wght' 600",
+ "'wght' 700",
+ "'wght' 800",
+ "'wght' 800, 'slnt' -1",
+ "'wght' 800, 'slnt' -2",
+ "'wght' 800, 'slnt' -3",
+ "'wght' 800, 'slnt' -4",
+ "'wght' 800, 'slnt' -5",
+ "'wght' 800, 'slnt' -6",
+ "'wght' 800, 'slnt' -7",
+ "'wght' 800, 'slnt' -8",
+ "'wght' 800, 'slnt' -9",
+ "'wght' 800, 'slnt' -10",
+ ];
+
+ return (
+ <>
+ {fontSettings.map((setting, index) => (
+
+ Inter variable font - {setting}
+
+ ))}
+
+
+
+
+ {'Invalid font variation settings - should fallback to default font'}
+
+
+
+
+ {/* Font Icons with custom axes */}
+ Material Symbols Sharp - 'wght' 400, 'FILL' 0
+
+ {String.fromCodePoint(59576)}
+
+ Material Symbols Sharp - 'wght' 100, 'FILL' 1
+
+ {String.fromCodePoint(59576)}
+
+ >
+ );
+}
+
function BackgroundColorExample(props: {}): React.Node {
return (
<>
@@ -1066,6 +1136,13 @@ const examples = [
return ;
},
},
+ {
+ title: 'Variable Font Settings',
+ name: 'fontVariationSettings',
+ render(): React.Node {
+ return ;
+ },
+ },
{
title: 'Font Style',
name: 'fontStyle',
diff --git a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js
index c2c8eb7084a4..6ecbdff70388 100644
--- a/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js
+++ b/packages/rn-tester/js/examples/TextInput/TextInputExample.android.js
@@ -522,6 +522,19 @@ const examples: Array = [
return ;
},
},
+ {
+ title: 'TextInput with font variation settings',
+ render: function (): React.Node {
+ return (
+
+ );
+ },
+ },
];
module.exports = ({