mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Share common ShadowNode functionality in BaseTextInputShadowNode for iOS (#48164)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/48164 [Changelog] [Internal] - Share common ShadowNode functionality in BaseTextInputShadowNode for iOS The current Android and iOS implementations have quite some overlapping functionality. Not sharing common logic makes it also harder to reuse this [functionality] for out of tree platforms. This change moves the current iOS implementation into a shared location. The next change allows to reuse it for Android. Reviewed By: NickGerleman Differential Revision: D66901676 fbshipit-source-id: a870155633875377d881fbd9f41fafb305672949
This commit is contained in:
committed by
Facebook GitHub Bot
parent
93c6be496e
commit
7d771de8a7
+27
@@ -211,6 +211,33 @@ void BaseTextInputProps::setProp(
|
||||
}
|
||||
}
|
||||
|
||||
TextAttributes BaseTextInputProps::getEffectiveTextAttributes(
|
||||
Float fontSizeMultiplier) const {
|
||||
auto result = TextAttributes::defaultTextAttributes();
|
||||
result.fontSizeMultiplier = fontSizeMultiplier;
|
||||
result.apply(textAttributes);
|
||||
|
||||
/*
|
||||
* These props are applied to `View`, therefore they must not be a part of
|
||||
* base text attributes.
|
||||
*/
|
||||
result.backgroundColor = clearColor();
|
||||
result.opacity = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ParagraphAttributes BaseTextInputProps::getEffectiveParagraphAttributes()
|
||||
const {
|
||||
auto result = paragraphAttributes;
|
||||
|
||||
if (!multiline) {
|
||||
result.maximumNumberOfLines = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SubmitBehavior BaseTextInputProps::getNonDefaultSubmitBehavior() const {
|
||||
if (submitBehavior == SubmitBehavior::Default) {
|
||||
return multiline ? SubmitBehavior::Newline : SubmitBehavior::BlurAndSubmit;
|
||||
|
||||
+9
-2
@@ -31,6 +31,15 @@ class BaseTextInputProps : public ViewProps, public BaseTextProps {
|
||||
const char* propName,
|
||||
const RawValue& value);
|
||||
|
||||
SubmitBehavior getNonDefaultSubmitBehavior() const;
|
||||
|
||||
/*
|
||||
* Accessors
|
||||
*/
|
||||
TextAttributes getEffectiveTextAttributes(Float fontSizeMultiplier) const;
|
||||
|
||||
ParagraphAttributes getEffectiveParagraphAttributes() const;
|
||||
|
||||
#pragma mark - Props
|
||||
|
||||
/*
|
||||
@@ -71,8 +80,6 @@ class BaseTextInputProps : public ViewProps, public BaseTextProps {
|
||||
SubmitBehavior submitBehavior{SubmitBehavior::Default};
|
||||
|
||||
bool multiline{false};
|
||||
|
||||
SubmitBehavior getNonDefaultSubmitBehavior() const;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/renderer/attributedstring/AttributedString.h>
|
||||
#include <react/renderer/attributedstring/AttributedStringBox.h>
|
||||
#include <react/renderer/components/text/BaseTextShadowNode.h>
|
||||
#include <react/renderer/components/textinput/BaseTextInputProps.h>
|
||||
#include <react/renderer/components/textinput/TextInputState.h>
|
||||
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
||||
#include <react/renderer/components/view/YogaLayoutableShadowNode.h>
|
||||
#include <react/renderer/core/LayoutConstraints.h>
|
||||
#include <react/renderer/core/LayoutContext.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutContext.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/*
|
||||
* Base `ShadowNode` for <TextInput> component.
|
||||
*/
|
||||
template <
|
||||
const char* concreteComponentName,
|
||||
typename ViewPropsT,
|
||||
typename ViewEventEmitterT,
|
||||
typename StateDataT,
|
||||
bool usesMapBufferForStateData = false>
|
||||
class BaseTextInputShadowNode : public ConcreteViewShadowNode<
|
||||
concreteComponentName,
|
||||
ViewPropsT,
|
||||
ViewEventEmitterT,
|
||||
StateDataT,
|
||||
usesMapBufferForStateData>,
|
||||
public BaseTextShadowNode {
|
||||
public:
|
||||
using BaseShadowNode = ConcreteViewShadowNode<
|
||||
concreteComponentName,
|
||||
ViewPropsT,
|
||||
ViewEventEmitterT,
|
||||
StateDataT,
|
||||
usesMapBufferForStateData>;
|
||||
|
||||
using BaseShadowNode::ConcreteViewShadowNode;
|
||||
|
||||
static ShadowNodeTraits BaseTraits() {
|
||||
auto traits = BaseShadowNode::BaseTraits();
|
||||
traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
|
||||
traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode);
|
||||
traits.set(ShadowNodeTraits::Trait::BaselineYogaNode);
|
||||
return traits;
|
||||
}
|
||||
|
||||
/*
|
||||
* Associates a shared `TextLayoutManager` with the node.
|
||||
* `TextInputShadowNode` uses the manager to measure text content
|
||||
* and construct `TextInputState` objects.
|
||||
*/
|
||||
void setTextLayoutManager(
|
||||
std::shared_ptr<const TextLayoutManager> textLayoutManager) {
|
||||
Sealable::ensureUnsealed();
|
||||
textLayoutManager_ = std::move(textLayoutManager);
|
||||
}
|
||||
|
||||
protected:
|
||||
Size measureContent(
|
||||
const LayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const override {
|
||||
const auto& props = BaseShadowNode::getConcreteProps();
|
||||
TextLayoutContext textLayoutContext{
|
||||
.pointScaleFactor = layoutContext.pointScaleFactor};
|
||||
return textLayoutManager_
|
||||
->measure(
|
||||
attributedStringBoxToMeasure(layoutContext),
|
||||
props.getEffectiveParagraphAttributes(),
|
||||
textLayoutContext,
|
||||
layoutConstraints)
|
||||
.size;
|
||||
}
|
||||
|
||||
void layout(LayoutContext layoutContext) override {
|
||||
updateStateIfNeeded(layoutContext);
|
||||
BaseShadowNode::layout(layoutContext);
|
||||
}
|
||||
|
||||
Float baseline(const LayoutContext& layoutContext, Size size) const override {
|
||||
const auto& props = BaseShadowNode::getConcreteProps();
|
||||
auto attributedString = getAttributedString(layoutContext);
|
||||
|
||||
if (attributedString.isEmpty()) {
|
||||
auto placeholderString = !props.placeholder.empty()
|
||||
? props.placeholder
|
||||
: BaseTextShadowNode::getEmptyPlaceholder();
|
||||
auto textAttributes =
|
||||
props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier);
|
||||
attributedString.appendFragment(
|
||||
{std::move(placeholderString), textAttributes, {}});
|
||||
}
|
||||
|
||||
// Yoga expects a baseline relative to the Node's border-box edge instead of
|
||||
// the content, so we need to adjust by the padding and border widths, which
|
||||
// have already been set by the time of baseline alignment
|
||||
auto top = YGNodeLayoutGetBorder(
|
||||
&(YogaLayoutableShadowNode::yogaNode_), YGEdgeTop) +
|
||||
YGNodeLayoutGetPadding(
|
||||
&(YogaLayoutableShadowNode::yogaNode_), YGEdgeTop);
|
||||
|
||||
AttributedStringBox attributedStringBox{attributedString};
|
||||
return textLayoutManager_->baseline(
|
||||
attributedStringBox,
|
||||
props.getEffectiveParagraphAttributes(),
|
||||
size) +
|
||||
top;
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* Creates a `State` object if needed.
|
||||
*/
|
||||
void updateStateIfNeeded(const LayoutContext& layoutContext) {
|
||||
Sealable::ensureUnsealed();
|
||||
const auto& stateData = BaseShadowNode::getStateData();
|
||||
const auto& reactTreeAttributedString = getAttributedString(layoutContext);
|
||||
|
||||
react_native_assert(textLayoutManager_);
|
||||
if (stateData.reactTreeAttributedString.isContentEqual(
|
||||
reactTreeAttributedString)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& props = BaseShadowNode::getConcreteProps();
|
||||
TextInputState newState(
|
||||
AttributedStringBox{reactTreeAttributedString},
|
||||
reactTreeAttributedString,
|
||||
props.paragraphAttributes,
|
||||
props.mostRecentEventCount);
|
||||
BaseShadowNode::setStateData(std::move(newState));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a `AttributedString` which represents text content of the node.
|
||||
*/
|
||||
AttributedString getAttributedString(
|
||||
const LayoutContext& layoutContext) const {
|
||||
const auto& props = BaseShadowNode::getConcreteProps();
|
||||
auto textAttributes =
|
||||
props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier);
|
||||
auto attributedString = AttributedString{};
|
||||
|
||||
attributedString.appendFragment(AttributedString::Fragment{
|
||||
.string = props.text,
|
||||
.textAttributes = textAttributes,
|
||||
// TODO: Is this really meant to be by value?
|
||||
.parentShadowView = ShadowView(*this)});
|
||||
|
||||
auto attachments = BaseTextShadowNode::Attachments{};
|
||||
BaseTextShadowNode::buildAttributedString(
|
||||
textAttributes, *this, attributedString, attachments);
|
||||
attributedString.setBaseTextAttributes(textAttributes);
|
||||
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an `AttributedStringBox` which represents text content that should
|
||||
* be used for measuring purposes. It might contain actual text value,
|
||||
* placeholder value or some character that represents the size of the font.
|
||||
*/
|
||||
AttributedStringBox attributedStringBoxToMeasure(
|
||||
const LayoutContext& layoutContext) const {
|
||||
bool meaningfulState = BaseShadowNode::getState() &&
|
||||
BaseShadowNode::getState()->getRevision() !=
|
||||
State::initialRevisionValue;
|
||||
if (meaningfulState) {
|
||||
const auto& stateData = BaseShadowNode::getStateData();
|
||||
auto attributedStringBox = stateData.attributedStringBox;
|
||||
if (attributedStringBox.getMode() ==
|
||||
AttributedStringBox::Mode::OpaquePointer ||
|
||||
!attributedStringBox.getValue().isEmpty()) {
|
||||
return stateData.attributedStringBox;
|
||||
}
|
||||
}
|
||||
|
||||
auto attributedString = meaningfulState
|
||||
? AttributedString{}
|
||||
: getAttributedString(layoutContext);
|
||||
|
||||
if (attributedString.isEmpty()) {
|
||||
const auto& props = BaseShadowNode::getConcreteProps();
|
||||
auto placeholder = props.placeholder;
|
||||
// Note: `zero-width space` is insufficient in some cases (e.g. when we
|
||||
// need to measure the "hight" of the font).
|
||||
// TODO T67606511: We will redefine the measurement of empty strings as
|
||||
// part of T67606511
|
||||
auto string = !placeholder.empty()
|
||||
? placeholder
|
||||
: BaseTextShadowNode::getEmptyPlaceholder();
|
||||
auto textAttributes =
|
||||
props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier);
|
||||
attributedString.appendFragment({string, textAttributes, {}});
|
||||
}
|
||||
return AttributedStringBox{attributedString};
|
||||
}
|
||||
|
||||
std::shared_ptr<const TextLayoutManager> textLayoutManager_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
-26
@@ -52,30 +52,4 @@ TextInputProps::TextInputProps(
|
||||
sourceProps.onChangeSync,
|
||||
{})){};
|
||||
|
||||
TextAttributes TextInputProps::getEffectiveTextAttributes(
|
||||
Float fontSizeMultiplier) const {
|
||||
auto result = TextAttributes::defaultTextAttributes();
|
||||
result.fontSizeMultiplier = fontSizeMultiplier;
|
||||
result.apply(textAttributes);
|
||||
|
||||
/*
|
||||
* These props are applied to `View`, therefore they must not be a part of
|
||||
* base text attributes.
|
||||
*/
|
||||
result.backgroundColor = clearColor();
|
||||
result.opacity = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ParagraphAttributes TextInputProps::getEffectiveParagraphAttributes() const {
|
||||
auto result = paragraphAttributes;
|
||||
|
||||
if (!multiline) {
|
||||
result.maximumNumberOfLines = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
-6
@@ -41,12 +41,6 @@ class TextInputProps final : public BaseTextInputProps {
|
||||
|
||||
bool onKeyPressSync{false};
|
||||
bool onChangeSync{false};
|
||||
|
||||
/*
|
||||
* Accessors
|
||||
*/
|
||||
TextAttributes getEffectiveTextAttributes(Float fontSizeMultiplier) const;
|
||||
ParagraphAttributes getEffectiveParagraphAttributes() const;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
-141
@@ -7,149 +7,8 @@
|
||||
|
||||
#include "TextInputShadowNode.h"
|
||||
|
||||
#include <react/debug/react_native_assert.h>
|
||||
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
||||
#include <react/renderer/attributedstring/AttributedStringBox.h>
|
||||
#include <react/renderer/attributedstring/TextAttributes.h>
|
||||
#include <react/renderer/core/LayoutConstraints.h>
|
||||
#include <react/renderer/core/LayoutContext.h>
|
||||
#include <react/renderer/core/conversions.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutContext.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
extern const char TextInputComponentName[] = "TextInput";
|
||||
|
||||
AttributedStringBox TextInputShadowNode::attributedStringBoxToMeasure(
|
||||
const LayoutContext& layoutContext) const {
|
||||
bool hasMeaningfulState =
|
||||
getState() && getState()->getRevision() != State::initialRevisionValue;
|
||||
|
||||
if (hasMeaningfulState) {
|
||||
auto attributedStringBox = getStateData().attributedStringBox;
|
||||
if (attributedStringBox.getMode() ==
|
||||
AttributedStringBox::Mode::OpaquePointer ||
|
||||
!attributedStringBox.getValue().isEmpty()) {
|
||||
return getStateData().attributedStringBox;
|
||||
}
|
||||
}
|
||||
|
||||
auto attributedString = hasMeaningfulState
|
||||
? AttributedString{}
|
||||
: getAttributedString(layoutContext);
|
||||
|
||||
if (attributedString.isEmpty()) {
|
||||
auto placeholder = getConcreteProps().placeholder;
|
||||
// Note: `zero-width space` is insufficient in some cases (e.g. when we need
|
||||
// to measure the "hight" of the font).
|
||||
// TODO T67606511: We will redefine the measurement of empty strings as part
|
||||
// of T67606511
|
||||
auto string = !placeholder.empty()
|
||||
? placeholder
|
||||
: BaseTextShadowNode::getEmptyPlaceholder();
|
||||
auto textAttributes = getConcreteProps().getEffectiveTextAttributes(
|
||||
layoutContext.fontSizeMultiplier);
|
||||
attributedString.appendFragment({string, textAttributes, {}});
|
||||
}
|
||||
|
||||
return AttributedStringBox{attributedString};
|
||||
}
|
||||
|
||||
AttributedString TextInputShadowNode::getAttributedString(
|
||||
const LayoutContext& layoutContext) const {
|
||||
auto textAttributes = getConcreteProps().getEffectiveTextAttributes(
|
||||
layoutContext.fontSizeMultiplier);
|
||||
auto attributedString = AttributedString{};
|
||||
|
||||
attributedString.appendFragment(AttributedString::Fragment{
|
||||
.string = getConcreteProps().text,
|
||||
.textAttributes = textAttributes,
|
||||
// TODO: Is this really meant to be by value?
|
||||
.parentShadowView = ShadowView(*this)});
|
||||
|
||||
auto attachments = Attachments{};
|
||||
BaseTextShadowNode::buildAttributedString(
|
||||
textAttributes, *this, attributedString, attachments);
|
||||
attributedString.setBaseTextAttributes(textAttributes);
|
||||
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
void TextInputShadowNode::setTextLayoutManager(
|
||||
std::shared_ptr<const TextLayoutManager> textLayoutManager) {
|
||||
ensureUnsealed();
|
||||
textLayoutManager_ = std::move(textLayoutManager);
|
||||
}
|
||||
|
||||
void TextInputShadowNode::updateStateIfNeeded(
|
||||
const LayoutContext& layoutContext) {
|
||||
ensureUnsealed();
|
||||
|
||||
auto reactTreeAttributedString = getAttributedString(layoutContext);
|
||||
const auto& state = getStateData();
|
||||
|
||||
react_native_assert(textLayoutManager_);
|
||||
if (state.reactTreeAttributedString.isContentEqual(
|
||||
reactTreeAttributedString)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto newState = TextInputState{};
|
||||
newState.attributedStringBox = AttributedStringBox{reactTreeAttributedString};
|
||||
newState.paragraphAttributes = getConcreteProps().paragraphAttributes;
|
||||
newState.reactTreeAttributedString = reactTreeAttributedString;
|
||||
newState.mostRecentEventCount = getConcreteProps().mostRecentEventCount;
|
||||
setStateData(std::move(newState));
|
||||
}
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
Size TextInputShadowNode::measureContent(
|
||||
const LayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const {
|
||||
TextLayoutContext textLayoutContext{};
|
||||
textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor;
|
||||
return textLayoutManager_
|
||||
->measure(
|
||||
attributedStringBoxToMeasure(layoutContext),
|
||||
getConcreteProps().getEffectiveParagraphAttributes(),
|
||||
textLayoutContext,
|
||||
layoutConstraints)
|
||||
.size;
|
||||
}
|
||||
|
||||
Float TextInputShadowNode::baseline(
|
||||
const LayoutContext& layoutContext,
|
||||
Size size) const {
|
||||
auto attributedString = getAttributedString(layoutContext);
|
||||
|
||||
if (attributedString.isEmpty()) {
|
||||
auto placeholderString = !getConcreteProps().placeholder.empty()
|
||||
? getConcreteProps().placeholder
|
||||
: BaseTextShadowNode::getEmptyPlaceholder();
|
||||
auto textAttributes = getConcreteProps().getEffectiveTextAttributes(
|
||||
layoutContext.fontSizeMultiplier);
|
||||
attributedString.appendFragment(
|
||||
{std::move(placeholderString), textAttributes, {}});
|
||||
}
|
||||
|
||||
// Yoga expects a baseline relative to the Node's border-box edge instead of
|
||||
// the content, so we need to adjust by the padding and border widths, which
|
||||
// have already been set by the time of baseline alignment
|
||||
auto top = YGNodeLayoutGetBorder(&yogaNode_, YGEdgeTop) +
|
||||
YGNodeLayoutGetPadding(&yogaNode_, YGEdgeTop);
|
||||
|
||||
AttributedStringBox attributedStringBox{std::move(attributedString)};
|
||||
return textLayoutManager_->baseline(
|
||||
attributedStringBox,
|
||||
getConcreteProps().getEffectiveParagraphAttributes(),
|
||||
size) +
|
||||
top;
|
||||
}
|
||||
|
||||
void TextInputShadowNode::layout(LayoutContext layoutContext) {
|
||||
updateStateIfNeeded(layoutContext);
|
||||
ConcreteViewShadowNode::layout(layoutContext);
|
||||
}
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
+4
-56
@@ -7,14 +7,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/renderer/attributedstring/AttributedString.h>
|
||||
#include <react/renderer/components/iostextinput/TextInputProps.h>
|
||||
#include <react/renderer/components/text/BaseTextShadowNode.h>
|
||||
#include <react/renderer/components/textinput/BaseTextInputShadowNode.h>
|
||||
#include <react/renderer/components/textinput/TextInputEventEmitter.h>
|
||||
#include <react/renderer/components/textinput/TextInputState.h>
|
||||
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
@@ -23,61 +19,13 @@ extern const char TextInputComponentName[];
|
||||
/*
|
||||
* `ShadowNode` for <TextInput> component.
|
||||
*/
|
||||
class TextInputShadowNode final : public ConcreteViewShadowNode<
|
||||
class TextInputShadowNode final : public BaseTextInputShadowNode<
|
||||
TextInputComponentName,
|
||||
TextInputProps,
|
||||
TextInputEventEmitter,
|
||||
TextInputState>,
|
||||
public BaseTextShadowNode {
|
||||
TextInputState> {
|
||||
public:
|
||||
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
||||
|
||||
static ShadowNodeTraits BaseTraits() {
|
||||
auto traits = ConcreteViewShadowNode::BaseTraits();
|
||||
traits.set(ShadowNodeTraits::Trait::LeafYogaNode);
|
||||
traits.set(ShadowNodeTraits::Trait::MeasurableYogaNode);
|
||||
traits.set(ShadowNodeTraits::Trait::BaselineYogaNode);
|
||||
return traits;
|
||||
}
|
||||
|
||||
/*
|
||||
* Associates a shared `TextLayoutManager` with the node.
|
||||
* `TextInputShadowNode` uses the manager to measure text content
|
||||
* and construct `TextInputState` objects.
|
||||
*/
|
||||
void setTextLayoutManager(
|
||||
std::shared_ptr<const TextLayoutManager> textLayoutManager);
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
Size measureContent(
|
||||
const LayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const override;
|
||||
void layout(LayoutContext layoutContext) override;
|
||||
|
||||
Float baseline(const LayoutContext& layoutContext, Size size) const override;
|
||||
|
||||
private:
|
||||
/*
|
||||
* Creates a `State` object if needed.
|
||||
*/
|
||||
void updateStateIfNeeded(const LayoutContext& layoutContext);
|
||||
|
||||
/*
|
||||
* Returns a `AttributedString` which represents text content of the node.
|
||||
*/
|
||||
AttributedString getAttributedString(
|
||||
const LayoutContext& layoutContext) const;
|
||||
|
||||
/*
|
||||
* Returns an `AttributedStringBox` which represents text content that should
|
||||
* be used for measuring purposes. It might contain actual text value,
|
||||
* placeholder value or some character that represents the size of the font.
|
||||
*/
|
||||
AttributedStringBox attributedStringBoxToMeasure(
|
||||
const LayoutContext& layoutContext) const;
|
||||
|
||||
std::shared_ptr<const TextLayoutManager> textLayoutManager_;
|
||||
using BaseTextInputShadowNode::BaseTextInputShadowNode;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
|
||||
Reference in New Issue
Block a user