Add accessibility and view props required for Android to C++ layer
Summary: Parses a set of props previously missing from C++ representation (they weren't required for iOS and core processing before). Changelog: [Internal] - Added missing fields for Android to C++ view props Reviewed By: sammy-SC Differential Revision: D33797489 fbshipit-source-id: 1625baa0c1a592fcef409a5f206496dff0368912
This commit is contained in:
Родитель
d264f1e725
Коммит
da72b5d02c
|
@ -10,6 +10,7 @@
|
|||
#include <butter/optional.h>
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
@ -75,6 +76,22 @@ constexpr bool operator!=(
|
|||
return !(rhs == lhs);
|
||||
}
|
||||
|
||||
struct AccessibilityLabelledBy {
|
||||
std::vector<std::string> value{};
|
||||
};
|
||||
|
||||
inline static bool operator==(
|
||||
AccessibilityLabelledBy const &lhs,
|
||||
AccessibilityLabelledBy const &rhs) {
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
|
||||
inline static bool operator!=(
|
||||
AccessibilityLabelledBy const &lhs,
|
||||
AccessibilityLabelledBy const &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
struct AccessibilityValue {
|
||||
butter::optional<int> min;
|
||||
butter::optional<int> max;
|
||||
|
@ -102,5 +119,11 @@ enum class ImportantForAccessibility {
|
|||
NoHideDescendants,
|
||||
};
|
||||
|
||||
enum class AccessibilityLiveRegion {
|
||||
None,
|
||||
Polite,
|
||||
Assertive,
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -43,6 +43,24 @@ AccessibilityProps::AccessibilityProps(
|
|||
"accessibilityLabel",
|
||||
sourceProps.accessibilityLabel,
|
||||
"")),
|
||||
accessibilityLabelledBy(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"accessibilityLabelledBy",
|
||||
sourceProps.accessibilityLabelledBy,
|
||||
{})),
|
||||
accessibilityLiveRegion(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"accessibilityLiveRegion",
|
||||
sourceProps.accessibilityLiveRegion,
|
||||
AccessibilityLiveRegion::None)),
|
||||
accessibilityRole(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"accessibilityRole",
|
||||
sourceProps.accessibilityRole,
|
||||
"")),
|
||||
accessibilityHint(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
|
|
|
@ -30,6 +30,10 @@ class AccessibilityProps {
|
|||
AccessibilityTraits accessibilityTraits{AccessibilityTraits::None};
|
||||
AccessibilityState accessibilityState;
|
||||
std::string accessibilityLabel{""};
|
||||
AccessibilityLabelledBy accessibilityLabelledBy{};
|
||||
AccessibilityLiveRegion accessibilityLiveRegion{
|
||||
AccessibilityLiveRegion::None};
|
||||
std::string accessibilityRole{""};
|
||||
std::string accessibilityHint{""};
|
||||
AccessibilityValue accessibilityValue;
|
||||
std::vector<AccessibilityAction> accessibilityActions{};
|
||||
|
|
|
@ -137,13 +137,53 @@ ViewProps::ViewProps(
|
|||
rawProps,
|
||||
"removeClippedSubviews",
|
||||
sourceProps.removeClippedSubviews,
|
||||
false)),
|
||||
false))
|
||||
#ifdef ANDROID
|
||||
,
|
||||
elevation(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"elevation",
|
||||
sourceProps.elevation,
|
||||
{})){};
|
||||
{})),
|
||||
nativeBackground(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"nativeBackgroundAndroid",
|
||||
sourceProps.nativeBackground,
|
||||
{})),
|
||||
nativeForeground(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"nativeForegroundAndroid",
|
||||
sourceProps.nativeForeground,
|
||||
{})),
|
||||
focusable(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"focusable",
|
||||
sourceProps.focusable,
|
||||
{})),
|
||||
hasTVPreferredFocus(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"hasTVPreferredFocus",
|
||||
sourceProps.hasTVPreferredFocus,
|
||||
{})),
|
||||
needsOffscreenAlphaCompositing(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"needsOffscreenAlphaCompositing",
|
||||
sourceProps.needsOffscreenAlphaCompositing,
|
||||
{})),
|
||||
renderToHardwareTextureAndroid(convertRawProp(
|
||||
context,
|
||||
rawProps,
|
||||
"renderToHardwareTextureAndroid",
|
||||
sourceProps.renderToHardwareTextureAndroid,
|
||||
{}))
|
||||
#endif
|
||||
{};
|
||||
|
||||
#pragma mark - Convenience Methods
|
||||
|
||||
|
|
|
@ -69,6 +69,18 @@ class ViewProps : public YogaStylableProps, public AccessibilityProps {
|
|||
|
||||
Float elevation{}; /* Android-only */
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
butter::optional<NativeDrawable> nativeBackground{};
|
||||
butter::optional<NativeDrawable> nativeForeground{};
|
||||
|
||||
bool focusable{false};
|
||||
bool hasTVPreferredFocus{false};
|
||||
bool needsOffscreenAlphaCompositing{false};
|
||||
bool renderToHardwareTextureAndroid{false};
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark - Convenience Methods
|
||||
|
||||
BorderMetrics resolveBorderMetrics(LayoutMetrics const &layoutMetrics) const;
|
||||
|
|
|
@ -35,7 +35,6 @@ void ViewShadowNode::initialize() noexcept {
|
|||
viewProps.pointerEvents == PointerEventsMode::None ||
|
||||
!viewProps.nativeId.empty() || viewProps.accessible ||
|
||||
viewProps.opacity != 1.0 || viewProps.transform != Transform{} ||
|
||||
viewProps.elevation != 0 ||
|
||||
(viewProps.zIndex.has_value() &&
|
||||
viewProps.yogaStyle.positionType() != YGPositionTypeStatic) ||
|
||||
viewProps.yogaStyle.display() == YGDisplayNone ||
|
||||
|
@ -46,6 +45,10 @@ void ViewShadowNode::initialize() noexcept {
|
|||
viewProps.importantForAccessibility != ImportantForAccessibility::Auto ||
|
||||
viewProps.removeClippedSubviews;
|
||||
|
||||
#ifdef ANDROID
|
||||
formsStackingContext = formsStackingContext || viewProps.elevation != 0;
|
||||
#endif
|
||||
|
||||
bool formsView = formsStackingContext ||
|
||||
isColorMeaningful(viewProps.backgroundColor) ||
|
||||
isColorMeaningful(viewProps.foregroundColor) ||
|
||||
|
@ -53,6 +56,14 @@ void ViewShadowNode::initialize() noexcept {
|
|||
!(viewProps.yogaStyle.border() == YGStyle::Edges{}) ||
|
||||
!viewProps.testId.empty();
|
||||
|
||||
#ifdef ANDROID
|
||||
formsView = formsView || viewProps.nativeBackground.has_value() ||
|
||||
viewProps.nativeForeground.has_value() || viewProps.focusable ||
|
||||
viewProps.hasTVPreferredFocus ||
|
||||
viewProps.needsOffscreenAlphaCompositing ||
|
||||
viewProps.renderToHardwareTextureAndroid;
|
||||
#endif
|
||||
|
||||
if (formsView) {
|
||||
traits_.set(ShadowNodeTraits::Trait::FormsView);
|
||||
} else {
|
||||
|
|
|
@ -263,5 +263,38 @@ inline void fromRawValue(
|
|||
}
|
||||
}
|
||||
|
||||
inline void fromRawValue(
|
||||
const PropsParserContext &context,
|
||||
const RawValue &value,
|
||||
AccessibilityLabelledBy &result) {
|
||||
if (value.hasType<std::string>()) {
|
||||
result.value.push_back((std::string)value);
|
||||
} else if (value.hasType<std::vector<std::string>>()) {
|
||||
result.value = (std::vector<std::string>)value;
|
||||
}
|
||||
}
|
||||
|
||||
inline void fromRawValue(
|
||||
const PropsParserContext &context,
|
||||
const RawValue &value,
|
||||
AccessibilityLiveRegion &result) {
|
||||
react_native_assert(value.hasType<std::string>());
|
||||
if (value.hasType<std::string>()) {
|
||||
auto string = (std::string)value;
|
||||
if (string == "none") {
|
||||
result = AccessibilityLiveRegion::None;
|
||||
} else if (string == "polite") {
|
||||
result = AccessibilityLiveRegion::Polite;
|
||||
} else if (string == "assertive") {
|
||||
result = AccessibilityLiveRegion::Assertive;
|
||||
} else {
|
||||
LOG(ERROR) << "Unsupported AccessibilityLiveRegion value: " << string;
|
||||
react_native_assert(false);
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << "Unsupported AccessibilityLiveRegion type";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -219,5 +219,48 @@ struct BorderMetrics {
|
|||
}
|
||||
};
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
struct NativeDrawable {
|
||||
enum class Kind {
|
||||
Ripple,
|
||||
ThemeAttr,
|
||||
};
|
||||
|
||||
struct Ripple {
|
||||
butter::optional<int32_t> color{};
|
||||
bool borderless{false};
|
||||
butter::optional<Float> rippleRadius{};
|
||||
|
||||
bool operator==(const Ripple &rhs) const {
|
||||
return std::tie(this->color, this->borderless, this->rippleRadius) ==
|
||||
std::tie(rhs.color, rhs.borderless, rhs.rippleRadius);
|
||||
}
|
||||
};
|
||||
|
||||
Kind kind;
|
||||
std::string themeAttr;
|
||||
Ripple ripple;
|
||||
|
||||
bool operator==(const NativeDrawable &rhs) const {
|
||||
if (this->kind != rhs.kind)
|
||||
return false;
|
||||
switch (this->kind) {
|
||||
case Kind::ThemeAttr:
|
||||
return this->themeAttr == rhs.themeAttr;
|
||||
case Kind::Ripple:
|
||||
return this->ripple == rhs.ripple;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator!=(const NativeDrawable &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
~NativeDrawable() = default;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -599,5 +599,58 @@ static inline ViewEvents convertRawProp(
|
|||
return result;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
static inline void fromRawValue(
|
||||
const PropsParserContext &context,
|
||||
RawValue const &rawValue,
|
||||
NativeDrawable &result) {
|
||||
auto map = (butter::map<std::string, RawValue>)rawValue;
|
||||
|
||||
auto typeIterator = map.find("type");
|
||||
react_native_assert(
|
||||
typeIterator != map.end() && typeIterator->second.hasType<std::string>());
|
||||
std::string type = (std::string)typeIterator->second;
|
||||
|
||||
if (type == "ThemeAttrAndroid") {
|
||||
auto attrIterator = map.find("attribute");
|
||||
react_native_assert(
|
||||
attrIterator != map.end() &&
|
||||
attrIterator->second.hasType<std::string>());
|
||||
|
||||
result = NativeDrawable{
|
||||
.kind = NativeDrawable::Kind::ThemeAttr,
|
||||
.themeAttr = (std::string)attrIterator->second,
|
||||
};
|
||||
} else if (type == "RippleAndroid") {
|
||||
auto color = map.find("color");
|
||||
auto borderless = map.find("borderless");
|
||||
auto rippleRadius = map.find("rippleRadius");
|
||||
|
||||
result = NativeDrawable{
|
||||
.kind = NativeDrawable::Kind::Ripple,
|
||||
.ripple =
|
||||
NativeDrawable::Ripple{
|
||||
.color = color != map.end() && color->second.hasType<int32_t>()
|
||||
? (int32_t)color->second
|
||||
: butter::optional<int32_t>{},
|
||||
.borderless = borderless != map.end() &&
|
||||
borderless->second.hasType<bool>()
|
||||
? (bool)borderless->second
|
||||
: false,
|
||||
.rippleRadius = rippleRadius != map.end() &&
|
||||
rippleRadius->second.hasType<Float>()
|
||||
? (Float)rippleRadius->second
|
||||
: butter::optional<Float>{},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
LOG(ERROR) << "Unknown native drawable type: " << type;
|
||||
react_native_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
Загрузка…
Ссылка в новой задаче