toast支持自定义文本颜色、背景色、背景模糊或阴影

Signed-off-by: Zhang Jinyu <zhangjinyu101@huawei.com>
Change-Id: Ia79a4a3c3815ed157d688242ea22b756101523cf
This commit is contained in:
Zhang Jinyu 2024-07-22 14:24:46 +08:00
parent 8b584a4e99
commit deccaadd37
6 changed files with 181 additions and 51 deletions

View File

@ -35,6 +35,10 @@ struct ToastInfo {
ToastShowMode showMode = ToastShowMode::DEFAULT;
int32_t alignment = 0;
std::optional<DimensionOffset> offset;
std::optional<Color> backgroundColor;
std::optional<Color> textColor;
std::optional<int32_t> backgroundBlurStyle;
std::optional<Shadow> shadow;
};
class ACE_EXPORT ToastLayoutProperty : public LayoutProperty {
DECLARE_ACE_TYPE(ToastLayoutProperty, LayoutProperty);

View File

@ -60,7 +60,7 @@ RefPtr<FrameNode> ToastView::CreateToastNode(const ToastInfo& toastInfo)
CHECK_NULL_RETURN(pattern, nullptr);
pattern->SetToastInfo(toastInfo);
pattern->SetTextNode(textNode);
UpdateTextLayoutProperty(textNode, toastInfo.message, toastInfo.isRightToLeft);
UpdateTextLayoutProperty(textNode, toastInfo.message, toastInfo.isRightToLeft, toastInfo.textColor);
UpdateToastContext(toastNode);
textNode->MountToParent(toastNode);
auto align = Alignment::ParseAlignment(toastInfo.alignment);
@ -83,7 +83,8 @@ RefPtr<FrameNode> ToastView::CreateToastNode(const ToastInfo& toastInfo)
}
void ToastView::UpdateTextLayoutProperty(
const RefPtr<FrameNode>& textNode, const std::string& message, bool isRightToLeft)
const RefPtr<FrameNode>& textNode, const std::string& message,
bool isRightToLeft, const std::optional<Color>& textColor)
{
auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
CHECK_NULL_VOID(textLayoutProperty);
@ -94,7 +95,7 @@ void ToastView::UpdateTextLayoutProperty(
auto fontSize = toastTheme->GetTextStyle().GetFontSize();
auto padding = toastTheme->GetPadding();
auto fontWeight = toastTheme->GetTextStyle().GetFontWeight();
auto textColor = toastTheme->GetTextStyle().GetTextColor();
auto defaultColor = toastTheme->GetTextStyle().GetTextColor();
textLayoutProperty->UpdateMaxFontScale(MAX_TOAST_SCALE);
PaddingProperty paddings;
paddings.top = NG::CalcLength(padding.Top());
@ -107,7 +108,7 @@ void ToastView::UpdateTextLayoutProperty(
textLayoutProperty->UpdateFontSize(fontSize);
textLayoutProperty->UpdateLayoutDirection((isRightToLeft ? TextDirection::RTL : TextDirection::LTR));
textLayoutProperty->UpdatePadding(paddings);
textLayoutProperty->UpdateTextColor(textColor);
textLayoutProperty->UpdateTextColor(textColor.value_or(defaultColor));
textLayoutProperty->UpdateFontWeight(fontWeight);
auto textContext = textNode->GetRenderContext();
CHECK_NULL_VOID(textContext);
@ -119,26 +120,12 @@ void ToastView::UpdateTextLayoutProperty(
}
}
bool ToastView::GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
{
auto colorMode = SystemProperties::GetColorMode();
if (shadowStyle == ShadowStyle::None) {
return true;
}
auto pipelineContext = PipelineContext::GetCurrentContext();
CHECK_NULL_RETURN(pipelineContext, false);
auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
if (!shadowTheme) {
return false;
}
shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
return true;
}
void ToastView::UpdateToastContext(const RefPtr<FrameNode>& toastNode)
{
auto toastContext = toastNode->GetRenderContext();
CHECK_NULL_VOID(toastContext);
auto pattern = toastNode->GetPattern<ToastPattern>();
CHECK_NULL_VOID(pattern);
auto pipelineContext = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipelineContext);
auto toastTheme = pipelineContext->GetTheme<ToastTheme>();
@ -164,14 +151,13 @@ void ToastView::UpdateToastContext(const RefPtr<FrameNode>& toastNode)
outerColorProp.SetColor(toastTheme->GetToastOuterBorderColor());
toastContext->UpdateOuterBorderColor(outerColorProp);
}
Shadow shadow;
if (GetShadowFromTheme(ShadowStyle::OuterDefaultMD, shadow)) {
toastContext->UpdateBackShadow(shadow);
}
auto toastInfo = pattern->GetToastInfo();
toastContext->UpdateBackShadow(toastInfo.shadow.value());
if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
toastContext->UpdateBackgroundColor(Color::TRANSPARENT);
toastContext->UpdateBackgroundColor(toastInfo.backgroundColor.value_or(Color::TRANSPARENT));
BlurStyleOption styleOption;
styleOption.blurStyle = BlurStyle::COMPONENT_ULTRA_THICK;
styleOption.blurStyle = static_cast<BlurStyle>(
toastInfo.backgroundBlurStyle.value_or(static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)));
styleOption.policy = BlurStyleActivePolicy::ALWAYS_ACTIVE;
toastContext->UpdateBackBlurStyle(styleOption);
} else {

View File

@ -30,9 +30,9 @@ public:
private:
static void UpdateTextLayoutProperty(
const RefPtr<FrameNode>& textNode, const std::string& message, bool isRightToLeft);
const RefPtr<FrameNode>& textNode, const std::string& message, bool isRightToLeft,
const std::optional<Color>& textColor);
static void UpdateToastContext(const RefPtr<FrameNode>& toastContext);
static bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow);
};
} // namespace OHOS::Ace::NG

View File

@ -194,6 +194,147 @@ bool GetToastOffset(napi_env env, napi_value offsetApi, std::optional<DimensionO
return true;
}
void GetToastBackgroundColor(napi_env env, napi_value backgroundColorNApi, std::optional<Color>& backgroundColor)
{
napi_valuetype valueType = napi_undefined;
napi_typeof(env, backgroundColorNApi, &valueType);
Color color;
backgroundColor = std::nullopt;
if (ParseNapiColor(env, backgroundColorNApi, color)) {
backgroundColor = color;
}
}
void GetToastTextColor(napi_env env, napi_value textColorNApi, std::optional<Color>& textColor)
{
napi_valuetype valueType = napi_undefined;
napi_typeof(env, textColorNApi, &valueType);
Color color;
textColor = std::nullopt;
if (ParseNapiColor(env, textColorNApi, color)) {
textColor = color;
}
}
void GetToastBackgroundBlurStyle(napi_env env,
napi_value backgroundBlurStyleNApi, std::optional<int32_t>& backgroundBlurStyle)
{
napi_valuetype valueType = napi_undefined;
napi_typeof(env, backgroundBlurStyleNApi, &valueType);
if (valueType == napi_number) {
int32_t num;
napi_get_value_int32(env, backgroundBlurStyleNApi, &num);
if (num >= 0 && num < BG_BLUR_STYLE_MAX_INDEX) {
backgroundBlurStyle = num;
}
}
}
bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
{
auto colorMode = SystemProperties::GetColorMode();
if (shadowStyle == ShadowStyle::None) {
return true;
}
auto container = Container::Current();
CHECK_NULL_RETURN(container, false);
auto pipelineContext = container->GetPipelineContext();
CHECK_NULL_RETURN(pipelineContext, false);
auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
if (!shadowTheme) {
return false;
}
shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
return true;
}
void GetToastObjectShadow(napi_env env, napi_value shadowNApi, Shadow& shadowProps)
{
napi_value radiusApi = nullptr;
napi_value colorApi = nullptr;
napi_value typeApi = nullptr;
napi_value fillApi = nullptr;
napi_get_named_property(env, shadowNApi, "radius", &radiusApi);
napi_get_named_property(env, shadowNApi, "color", &colorApi);
napi_get_named_property(env, shadowNApi, "type", &typeApi);
napi_get_named_property(env, shadowNApi, "fill", &fillApi);
double radius = 0.0;
napi_get_value_double(env, radiusApi, &radius);
if (LessNotEqual(radius, 0.0)) {
radius = 0.0;
}
shadowProps.SetBlurRadius(radius);
Color color;
ShadowColorStrategy shadowColorStrategy;
if (ParseShadowColorStrategy(env, colorApi, shadowColorStrategy)) {
shadowProps.SetShadowColorStrategy(shadowColorStrategy);
} else if (ParseNapiColor(env, colorApi, color)) {
shadowProps.SetColor(color);
}
napi_valuetype valueType = GetValueType(env, typeApi);
int32_t shadowType = static_cast<int32_t>(ShadowType::COLOR);
if (valueType == napi_number) {
napi_get_value_int32(env, typeApi, &shadowType);
}
if (shadowType != static_cast<int32_t>(ShadowType::BLUR)) {
shadowType = static_cast<int32_t>(ShadowType::COLOR);
}
shadowType =
std::clamp(shadowType, static_cast<int32_t>(ShadowType::COLOR), static_cast<int32_t>(ShadowType::BLUR));
shadowProps.SetShadowType(static_cast<ShadowType>(shadowType));
valueType = GetValueType(env, fillApi);
bool isFilled = false;
if (valueType == napi_boolean) {
napi_get_value_bool(env, fillApi, &isFilled);
}
shadowProps.SetIsFilled(isFilled);
}
void GetToastShadow(napi_env env, napi_value shadowNApi, std::optional<Shadow>& shadow)
{
Shadow shadowProps;
napi_valuetype valueType = napi_undefined;
napi_typeof(env, shadowNApi, &valueType);
GetShadowFromTheme(ShadowStyle::OuterDefaultMD, shadowProps);
if (valueType == napi_number) {
int32_t num = 0;
napi_get_value_int32(env, shadowNApi, &num);
auto style = static_cast<ShadowStyle>(num);
GetShadowFromTheme(style, shadowProps);
} else if (valueType == napi_object) {
napi_value offsetXApi = nullptr;
napi_value offsetYApi = nullptr;
napi_get_named_property(env, shadowNApi, "offsetX", &offsetXApi);
napi_get_named_property(env, shadowNApi, "offsetY", &offsetYApi);
ResourceInfo recv;
bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
if (ParseResourceParam(env, offsetXApi, recv)) {
auto resourceWrapper = CreateResourceWrapper(recv);
auto offsetX = resourceWrapper->GetDimension(recv.resId);
double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
shadowProps.SetOffsetX(xValue);
} else {
CalcDimension offsetX;
if (ParseNapiDimension(env, offsetX, offsetXApi, DimensionUnit::VP)) {
double xValue = isRtl ? offsetX.Value() * (-1) : offsetX.Value();
shadowProps.SetOffsetX(xValue);
}
}
if (ParseResourceParam(env, offsetYApi, recv)) {
auto resourceWrapper = CreateResourceWrapper(recv);
auto offsetY = resourceWrapper->GetDimension(recv.resId);
shadowProps.SetOffsetY(offsetY.Value());
} else {
CalcDimension offsetY;
if (ParseNapiDimension(env, offsetY, offsetYApi, DimensionUnit::VP)) {
shadowProps.SetOffsetY(offsetY.Value());
}
}
GetToastObjectShadow(env, shadowNApi, shadowProps);
}
shadow = shadowProps;
}
bool GetToastParams(napi_env env, napi_value argv, NG::ToastInfo& toastInfo)
{
napi_value messageNApi = nullptr;
@ -202,6 +343,10 @@ bool GetToastParams(napi_env env, napi_value argv, NG::ToastInfo& toastInfo)
napi_value showModeNApi = nullptr;
napi_value alignmentApi = nullptr;
napi_value offsetApi = nullptr;
napi_value backgroundColorNApi = nullptr;
napi_value textColorNApi = nullptr;
napi_value backgroundBlurStyleNApi = nullptr;
napi_value shadowNApi = nullptr;
napi_valuetype valueType = napi_undefined;
napi_typeof(env, argv, &valueType);
@ -217,6 +362,10 @@ bool GetToastParams(napi_env env, napi_value argv, NG::ToastInfo& toastInfo)
napi_get_named_property(env, argv, "showMode", &showModeNApi);
napi_get_named_property(env, argv, "alignment", &alignmentApi);
napi_get_named_property(env, argv, "offset", &offsetApi);
napi_get_named_property(env, argv, "backgroundColor", &backgroundColorNApi);
napi_get_named_property(env, argv, "textColor", &textColorNApi);
napi_get_named_property(env, argv, "backgroundBlurStyle", &backgroundBlurStyleNApi);
napi_get_named_property(env, argv, "shadow", &shadowNApi);
} else {
NapiThrow(env, "The type of parameters is incorrect.", ERROR_CODE_PARAM_INVALID);
return false;
@ -229,6 +378,10 @@ bool GetToastParams(napi_env env, napi_value argv, NG::ToastInfo& toastInfo)
!GetToastOffset(env, offsetApi, toastInfo.offset)) {
return false;
}
GetToastBackgroundColor(env, backgroundColorNApi, toastInfo.backgroundColor);
GetToastTextColor(env, textColorNApi, toastInfo.textColor);
GetToastBackgroundBlurStyle(env, backgroundBlurStyleNApi, toastInfo.backgroundBlurStyle);
GetToastShadow(env, shadowNApi, toastInfo.shadow);
return true;
}
@ -813,24 +966,6 @@ std::optional<NG::BorderStyleProperty> GetBorderStyleProps(
return std::nullopt;
}
bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
{
auto colorMode = SystemProperties::GetColorMode();
if (shadowStyle == ShadowStyle::None) {
return true;
}
auto container = Container::Current();
CHECK_NULL_RETURN(container, false);
auto pipelineContext = container->GetPipelineContext();
CHECK_NULL_RETURN(pipelineContext, false);
auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
if (!shadowTheme) {
return false;
}
shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
return true;
}
void GetNapiObjectShadow(napi_env env, const std::shared_ptr<PromptAsyncContext>& asyncContext, Shadow& shadow)
{
napi_value radiusApi = nullptr;

View File

@ -1426,6 +1426,7 @@ HWTEST_F(OverlayTestNg, ToastTest006, TestSize.Level1)
{
auto offset = DimensionOffset(MENU_OFFSET);
ToastInfo toastInfo = { MESSAGE, 0, BOTTOMSTRING, true, ToastShowMode::DEFAULT, 0, offset };
const std::optional<Color> textColor = Color::RED;
auto toastNode = ToastView::CreateToastNode(toastInfo);
ASSERT_NE(toastNode, nullptr);
auto toastPattern = toastNode->GetPattern<ToastPattern>();
@ -1439,7 +1440,7 @@ HWTEST_F(OverlayTestNg, ToastTest006, TestSize.Level1)
int32_t settingApiVersion = 12;
int32_t backupApiVersion = MockContainer::Current()->GetApiTargetVersion();
MockContainer::Current()->SetApiTargetVersion(settingApiVersion);
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, false);
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, false, textColor);
MockContainer::Current()->SetApiTargetVersion(backupApiVersion);
}

View File

@ -269,6 +269,7 @@ HWTEST_F(OverlayTestUpdate, ToastTest001, TestSize.Level1)
*/
auto offset = DimensionOffset(MENU_OFFSET);
ToastInfo toastInfo = { MESSAGE, 0, BOTTOMSTRING, false, ToastShowMode::TOP_MOST, 0, offset };
const std::optional<Color> textColor = Color::RED;
/**
* @tc.steps: step2. create ToastNode toastPattern1.
*/
@ -295,7 +296,7 @@ HWTEST_F(OverlayTestUpdate, ToastTest001, TestSize.Level1)
/**
* @tc.steps: step6. test UpdateTextLayoutProperty.
*/
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, false);
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, false, textColor);
EXPECT_EQ(textLayoutProperty->GetTextOverflow(), TextOverflow::ELLIPSIS);
EXPECT_EQ(textLayoutProperty->GetEllipsisMode(), EllipsisMode::TAIL);
MockContainer::Current()->SetApiTargetVersion(backupApiVersion);
@ -313,6 +314,7 @@ HWTEST_F(OverlayTestUpdate, ToastTest002, TestSize.Level1)
*/
auto offset = DimensionOffset(MENU_OFFSET);
ToastInfo toastInfo = { MESSAGE, 0, BOTTOMSTRING, true, ToastShowMode::TOP_MOST, 0, offset };
const std::optional<Color> textColor = Color::RED;
auto toastNode = ToastView::CreateToastNode(toastInfo);
ASSERT_NE(toastNode, nullptr);
auto toastPattern1 = toastNode->GetPattern<ToastPattern>();
@ -333,7 +335,7 @@ HWTEST_F(OverlayTestUpdate, ToastTest002, TestSize.Level1)
/**
* @tc.steps: step4. test VERSION_TWELVEversion and UpdateTextLayoutProperty.
*/
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, false);
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, false, textColor);
EXPECT_EQ(textLayoutProperty->GetTextOverflow(), TextOverflow::ELLIPSIS);
EXPECT_EQ(textLayoutProperty->GetEllipsisMode(), EllipsisMode::TAIL);
MockContainer::Current()->SetApiTargetVersion(backupApiVersion);
@ -351,6 +353,7 @@ HWTEST_F(OverlayTestUpdate, ToastTest003, TestSize.Level1)
*/
auto offset = DimensionOffset(MENU_OFFSET);
ToastInfo toastInfo = { MESSAGE, 1, BOTTOMSTRING, false, ToastShowMode::DEFAULT, 0, offset };
const std::optional<Color> textColor = Color::RED;
/**
* @tc.steps: step2. CreateToastNode toastPattern1.
*/
@ -374,7 +377,7 @@ HWTEST_F(OverlayTestUpdate, ToastTest003, TestSize.Level1)
/**
* @tc.steps: step5. test UpdateTextLayoutProperty .
*/
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, false);
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, false, textColor);
auto textval = textLayoutProperty->GetTextOverflow();
auto textva2 = textLayoutProperty->GetEllipsisMode();
EXPECT_EQ(textval, TextOverflow::ELLIPSIS);
@ -394,6 +397,7 @@ HWTEST_F(OverlayTestUpdate, ToastTest004, TestSize.Level1)
*/
auto offset = DimensionOffset(MENU_OFFSET);
ToastInfo toastInfo = { MESSAGE, 0, BOTTOMSTRING, true, ToastShowMode::DEFAULT, 0, offset };
const std::optional<Color> textColor = Color::RED;
auto toastNode = ToastView::CreateToastNode(toastInfo);
ASSERT_NE(toastNode, nullptr);
auto toastPattern = toastNode->GetPattern<ToastPattern>();
@ -414,7 +418,7 @@ HWTEST_F(OverlayTestUpdate, ToastTest004, TestSize.Level1)
/**
* @tc.steps: step4.Test UpdateTextLayoutProperty for diff toastInfo.
*/
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, true);
ToastView::UpdateTextLayoutProperty(textNode, MESSAGE, true, textColor);
auto textval1 = textLayoutProperty->GetLayoutDirection();
auto textval2 = textLayoutProperty->GetTextOverflow();
auto textval3 = textLayoutProperty->GetEllipsisMode();