diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 72165e54271..3b0b6c317ef 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -212,6 +212,7 @@ public class ReactTextInputManager extends BaseViewManager #include -#include - using namespace facebook::jni; namespace facebook { @@ -33,44 +31,52 @@ void AndroidTextInputShadowNode::setContextContainer( AttributedString AndroidTextInputShadowNode::getAttributedString( bool usePlaceholders) const { - auto textAttributes = TextAttributes::defaultTextAttributes(); - textAttributes.apply(getProps()->textAttributes); - // Use BaseTextShadowNode to get attributed string from children - auto const &attributedString = - BaseTextShadowNode::getAttributedString(textAttributes, *this); + auto childTextAttributes = TextAttributes::defaultTextAttributes(); + childTextAttributes.apply(getProps()->textAttributes); + auto attributedString = + BaseTextShadowNode::getAttributedString(childTextAttributes, *this); + + // BaseTextShadowNode only gets children. We must detect and prepend text + // value attributes manually. + if (!getProps()->text.empty()) { + auto textAttributes = TextAttributes::defaultTextAttributes(); + textAttributes.apply(getProps()->textAttributes); + auto fragment = AttributedString::Fragment{}; + fragment.string = getProps()->text; + fragment.textAttributes = textAttributes; + fragment.parentShadowView = ShadowView(*this); + attributedString.prependFragment(fragment); + + // We know this is not empty, because we at least have the `text` value + return attributedString; + } + + // No need to use placeholder if we have text at this point. if (!attributedString.isEmpty()) { return attributedString; } - if (!getProps()->text.empty() || usePlaceholders) { - // If the BaseTextShadowNode didn't detect any child Text nodes, we - // may actually just have a `text` attribute. - // TODO: figure out why BaseTextShadowNode doesn't pick this up, this - // is a bug. A minimal Playground example that triggers this: P122991121 - auto textAttributedString = AttributedString{}; - auto fragment = AttributedString::Fragment{}; - fragment.string = getProps()->text; - if (usePlaceholders) { - // Return placeholder text instead, if text was empty. - if (fragment.string.empty()) { - fragment.string = getProps()->placeholder; - } - // For measurement purposes, we want to make sure that there's at least a - // single character in the string so that the measured height is greater - // than zero. Otherwise, empty TextInputs with no placeholder don't - // display at all. - if (fragment.string.empty()) { - fragment.string = " "; - } - } - fragment.textAttributes = textAttributes; - fragment.parentShadowView = ShadowView(*this); - textAttributedString.appendFragment(fragment); - return textAttributedString; + // Return placeholder text, since text and children are empty. + auto textAttributedString = AttributedString{}; + auto fragment = AttributedString::Fragment{}; + fragment.string = getProps()->placeholder; + + // For measurement purposes, we want to make sure that there's at least a + // single character in the string so that the measured height is greater + // than zero. Otherwise, empty TextInputs with no placeholder don't + // display at all. + if (fragment.string.empty() && usePlaceholders) { + fragment.string = " "; } - return attributedString; + auto textAttributes = TextAttributes::defaultTextAttributes(); + textAttributes.apply(getProps()->textAttributes); + + fragment.textAttributes = textAttributes; + fragment.parentShadowView = ShadowView(*this); + textAttributedString.appendFragment(fragment); + return textAttributedString; } void AndroidTextInputShadowNode::setTextLayoutManager(