diff --git a/frameworks/bridge/declarative_frontend/jsview/js_popups.cpp b/frameworks/bridge/declarative_frontend/jsview/js_popups.cpp index 3a1411f4f8d2c8c006415c455a5e25b3244200c4..07f756579b457e17df55e1d145de03b33f2ddacf 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_popups.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_popups.cpp @@ -929,6 +929,18 @@ void ParseContentPreviewAnimationOptionsParam(const JSCallbackInfo& info, const } } +void ParsePreviewBorderRadiusParam(const JSRef& menuContentOptions, NG::MenuParam& menuParam) +{ + if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_SIXTEEN)) { + return; + } + auto previewBorderRadiusValue = menuContentOptions->GetProperty("previewBorderRadius"); + NG::BorderRadiusProperty previewBorderRadius; + if (JSViewAbstract::ParseBorderRadius(previewBorderRadiusValue, previewBorderRadius)) { + menuParam.previewBorderRadius = previewBorderRadius; + } +} + void ParseBindContentOptionParam(const JSCallbackInfo& info, const JSRef& args, NG::MenuParam& menuParam, std::function& previewBuildFunc) { @@ -947,6 +959,7 @@ void ParseBindContentOptionParam(const JSCallbackInfo& info, const JSRef& if (preview->ToNumber() == 1) { menuParam.previewMode = MenuPreviewMode::IMAGE; ParseContentPreviewAnimationOptionsParam(info, menuContentOptions, menuParam); + ParsePreviewBorderRadiusParam(menuContentOptions, menuParam); } } else { previewBuilderFunc = AceType::MakeRefPtr(JSRef::Cast(preview)); @@ -961,6 +974,7 @@ void ParseBindContentOptionParam(const JSCallbackInfo& info, const JSRef& }; menuParam.previewMode = MenuPreviewMode::CUSTOM; ParseContentPreviewAnimationOptionsParam(info, menuContentOptions, menuParam); + ParsePreviewBorderRadiusParam(menuContentOptions, menuParam); } } diff --git a/frameworks/core/components_ng/pattern/menu/menu_pattern.h b/frameworks/core/components_ng/pattern/menu/menu_pattern.h index 1f926e820ee00cde18488b6a65294b709b42751b..73738ef3577fa882189b77d1428e80dc79a4bb7c 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_pattern.h +++ b/frameworks/core/components_ng/pattern/menu/menu_pattern.h @@ -19,6 +19,7 @@ #include #include +#include "base/geometry/dimension.h" #include "base/geometry/ng/size_t.h" #include "base/memory/referenced.h" #include "base/utils/utils.h" @@ -59,7 +60,7 @@ struct MenuItemInfo { struct PreviewMenuAnimationInfo { float previewScale = -1.0f; float menuScale = -1.0f; - float borderRadius = -1.0f; + BorderRadiusProperty borderRadius = BorderRadiusProperty(Dimension(-1.0f)); // for hoverScale animation float clipRate = -1.0f; diff --git a/frameworks/core/components_ng/pattern/menu/menu_view.cpp b/frameworks/core/components_ng/pattern/menu/menu_view.cpp index 9dda8984427a8ca24abbbe5e21cf99b1dc623935..6541594cd7a29443f6412a0555a145c0a70fdf59 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_view.cpp +++ b/frameworks/core/components_ng/pattern/menu/menu_view.cpp @@ -38,6 +38,7 @@ #include "core/components_ng/pattern/scroll/scroll_pattern.h" #include "core/components_ng/pattern/stack/stack_pattern.h" #include "core/components_ng/pattern/text/text_pattern.h" +#include "core/components_ng/property/menu_property.h" #include "core/components_v2/inspector/inspector_constants.h" namespace OHOS::Ace::NG { @@ -361,7 +362,7 @@ void UpdateOpacityInFinishEvent(const RefPtr& previewNode, const RefP } void UpdatePreviewVisibleAreaByFrame(const RefPtr& clipContext, - const RefPtr& previewPattern, float radius, float rate) + const RefPtr& previewPattern, const BorderRadiusProperty& radius, float rate) { CHECK_NULL_VOID(previewPattern && clipContext); // clip area start by actual image size after contain stack container and squeezed by parent proc @@ -378,10 +379,49 @@ void UpdatePreviewVisibleAreaByFrame(const RefPtr& clipContext, RoundRect roundRectInstance; roundRectInstance.SetRect(RectF(OffsetF((1 - rate) * clipOffset.GetX(), (1 - rate) * clipOffset.GetY()), SizeF(curentClipAreaWidth, curentClipAreaHeight))); - roundRectInstance.SetCornerRadius(rate * radius); + CHECK_NULL_VOID(radius.radiusTopLeft); + roundRectInstance.SetCornerRadius( + RoundRect::TOP_LEFT_POS, rate * radius.radiusTopLeft->Value(), rate * radius.radiusTopLeft->Value()); + CHECK_NULL_VOID(radius.radiusTopRight); + roundRectInstance.SetCornerRadius( + RoundRect::TOP_RIGHT_POS, rate * radius.radiusTopRight->Value(), rate * radius.radiusTopRight->Value()); + CHECK_NULL_VOID(radius.radiusBottomLeft); + roundRectInstance.SetCornerRadius( + RoundRect::BOTTOM_LEFT_POS, rate * radius.radiusBottomLeft->Value(), rate * radius.radiusBottomLeft->Value()); + CHECK_NULL_VOID(radius.radiusBottomRight); + roundRectInstance.SetCornerRadius(RoundRect::BOTTOM_RIGHT_POS, rate * radius.radiusBottomRight->Value(), + rate * radius.radiusBottomRight->Value()); clipContext->ClipWithRoundRect(roundRectInstance); } +BorderRadiusProperty GetHoverPreviewBorderRadius( + const RefPtr& previewPattern, const RefPtr& menuTheme) +{ + CHECK_NULL_RETURN(previewPattern, {}); + auto menuWrapper = previewPattern->GetMenuWrapper(); + CHECK_NULL_RETURN(menuWrapper, {}); + auto menuWrapperPattern = menuWrapper->GetPattern(); + CHECK_NULL_RETURN(menuWrapperPattern, {}); + CHECK_NULL_RETURN(menuTheme, {}); + auto radius = menuTheme->GetPreviewBorderRadius().ConvertToPx(); + auto menuParam = menuWrapperPattern->GetMenuParam(); + CHECK_NULL_RETURN(menuParam.previewBorderRadius, {}); + if (menuParam.previewBorderRadius.has_value() && !menuParam.previewBorderRadius->multiValued) { + auto paramRadius = menuParam.previewBorderRadius->radiusTopLeft; + radius = (paramRadius->Unit() == DimensionUnit::PERCENT) + ? paramRadius->Value() * previewPattern->GetCustomPreviewWidth() + : paramRadius->ConvertToPx(); + } + + if (menuParam.previewBorderRadius.has_value() && menuParam.previewBorderRadius->multiValued) { + BorderRadiusProperty previewBorderRadius; + previewBorderRadius.SetRadius(Dimension(radius)); + previewBorderRadius.UpdateWithCheck(menuParam.previewBorderRadius.value()); + return previewBorderRadius; + } + return BorderRadiusProperty(Dimension(radius)); +} + void UpdateHoverImagePreviewScale(const RefPtr& hoverImageStackNode, const RefPtr& previewPattern, const RefPtr& menuTheme, bool isScaleNearEqual) { @@ -414,13 +454,14 @@ void UpdateHoverImagePreviewScale(const RefPtr& hoverImageStackNode, CHECK_NULL_VOID(menuWrapper); auto menuWrapperPattern = menuWrapper->GetPattern(); CHECK_NULL_VOID(menuWrapperPattern); - auto radius = menuTheme->GetPreviewBorderRadius().ConvertToPx(); - auto callback = [menuWrapperPattern, previewPattern, stackContext, scaleFrom, scaleTo, radius](float rate) { + BorderRadiusProperty previewRadius = GetHoverPreviewBorderRadius(previewPattern, menuTheme); + + auto callback = [menuWrapperPattern, previewPattern, stackContext, scaleFrom, scaleTo, previewRadius](float rate) { CHECK_NULL_VOID(menuWrapperPattern && !menuWrapperPattern->IsHide()); menuWrapperPattern->SetAnimationPreviewScale(rate * (scaleTo - scaleFrom) + scaleFrom); menuWrapperPattern->SetAnimationClipRate(rate); - menuWrapperPattern->SetAnimationBorderRadius(rate * radius); - UpdatePreviewVisibleAreaByFrame(stackContext, previewPattern, radius, rate); + menuWrapperPattern->SetAnimationBorderRadius(rate, previewRadius); + UpdatePreviewVisibleAreaByFrame(stackContext, previewPattern, previewRadius, rate); }; auto animateProperty = AceType::MakeRefPtr(-1.0, std::move(callback)); @@ -706,6 +747,25 @@ void SetAccessibilityPixelMap(const RefPtr& targetNode, RefPtr& previewNode, const MenuParam& menuParam) +{ + CHECK_NULL_RETURN(previewNode, {}); + auto pipelineContext = previewNode->GetContextWithCheck(); + CHECK_NULL_RETURN(pipelineContext, {}); + auto menuTheme = pipelineContext->GetTheme(); + CHECK_NULL_RETURN(menuTheme, {}); + auto previewBorderRadiusValue = menuTheme->GetPreviewBorderRadius(); + + CHECK_NULL_RETURN(menuParam.previewBorderRadius, {}); + if (menuParam.previewBorderRadius.has_value()) { + BorderRadiusProperty previewBorderRadius; + previewBorderRadius.SetRadius(Dimension(previewBorderRadiusValue)); + previewBorderRadius.UpdateWithCheck(menuParam.previewBorderRadius.value()); + return previewBorderRadius; + } + return BorderRadiusProperty((Dimension(previewBorderRadiusValue))); +} + void SetPixelMap(const RefPtr& target, const RefPtr& wrapperNode, const RefPtr& hoverImageStackNode, const RefPtr& previewNode, const MenuParam& menuParam) { @@ -746,8 +806,9 @@ void SetPixelMap(const RefPtr& target, const RefPtr& wrapp auto imageContext = imageNode->GetRenderContext(); CHECK_NULL_VOID(imageContext); + BorderRadiusProperty borderRadius = GetPixelMapPreviewBorderRadius(previewNode, menuParam); if (menuParam.previewBorderRadius) { - imageContext->UpdateBorderRadius(menuParam.previewBorderRadius.value()); + imageContext->UpdateBorderRadius(borderRadius); } imageNode->MarkModifyDone(); imageNode->MountToParent(wrapperNode); diff --git a/frameworks/core/components_ng/pattern/menu/preview/menu_preview_pattern.cpp b/frameworks/core/components_ng/pattern/menu/preview/menu_preview_pattern.cpp index 5205703203d272107dc104bf9feedb3c4d7463d7..5d5ee63b2ba2c313b2913f4b883d82b3b9c0872b 100644 --- a/frameworks/core/components_ng/pattern/menu/preview/menu_preview_pattern.cpp +++ b/frameworks/core/components_ng/pattern/menu/preview/menu_preview_pattern.cpp @@ -90,8 +90,8 @@ void ShowScaleAnimation(const RefPtr& context, const RefPtr& context, const RefPtr& frameNode, bool isShowHoverImage) +void ShowBorderRadiusAndShadowAnimation(const RefPtr& context, const RefPtr& frameNode, + bool isShowHoverImage, const MenuParam& menuParam) { CHECK_NULL_VOID(context && frameNode); auto pipeline = frameNode->GetContext(); @@ -106,6 +106,11 @@ void ShowBorderRadiusAndShadowAnimation( auto previewAnimationDuration = menuTheme->GetPreviewAnimationDuration(); auto previewBorderRadius = menuTheme->GetPreviewBorderRadius(); + BorderRadiusProperty borderRadius; + borderRadius.SetRadius(Dimension(previewBorderRadius)); + if (menuParam.previewBorderRadius.has_value()) { + borderRadius.UpdateWithCheck(menuParam.previewBorderRadius.value()); + } auto delay = isShowHoverImage ? menuTheme->GetHoverImageDelayDuration() : 0; AnimationOption option; option.SetDuration(previewAnimationDuration); @@ -117,18 +122,16 @@ void ShowBorderRadiusAndShadowAnimation( option.SetDelay(delay); context->UpdateBorderRadius(context->GetBorderRadius().value_or(BorderRadiusProperty())); - pipeline->AddAfterLayoutTask([option, context, previewBorderRadius, shadow, isShowHoverImage]() { + pipeline->AddAfterLayoutTask([option, context, borderRadius, shadow, isShowHoverImage]() { AnimationUtils::Animate( option, - [context, previewBorderRadius, shadow, isShowHoverImage]() mutable { + [context, borderRadius, shadow, isShowHoverImage]() mutable { CHECK_NULL_VOID(context && shadow); auto color = shadow->GetColor(); auto newColor = Color::FromARGB(100, color.GetRed(), color.GetGreen(), color.GetBlue()); shadow->SetColor(newColor); context->UpdateBackShadow(shadow.value()); CHECK_NULL_VOID(!isShowHoverImage); - BorderRadiusProperty borderRadius; - borderRadius.SetRadius(previewBorderRadius); context->UpdateBorderRadius(borderRadius); }, option.GetOnFinishEvent()); @@ -161,7 +164,17 @@ bool MenuPreviewPattern::OnDirtyLayoutWrapperSwap(const RefPtr& d context->UpdateBackgroundColor(Color::TRANSPARENT); context->SetClipToBounds(true); context->UpdateClipEdge(true); - ShowBorderRadiusAndShadowAnimation(context, host, isShowHoverImage_); + + auto preview = host->GetHostNode(); + CHECK_NULL_RETURN(preview, false); + auto previewPattern = preview->GetPattern(); + CHECK_NULL_RETURN(previewPattern, false); + auto previewMenuWrapper = previewPattern->GetMenuWrapper(); + CHECK_NULL_RETURN(previewMenuWrapper, false); + auto menuWrapperPattern = previewMenuWrapper->GetPattern(); + CHECK_NULL_RETURN(menuWrapperPattern, false); + auto menuParam = menuWrapperPattern->GetMenuParam(); + ShowBorderRadiusAndShadowAnimation(context, host, isShowHoverImage_, menuParam); auto menuWrapper = GetMenuWrapper(); auto menuPattern = GetMenuPattern(menuWrapper); DragAnimationHelper::UpdateGatherNodeToTop(); diff --git a/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.cpp b/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.cpp index f4beb55d3ad5673e425641289513e7c4585d2a46..0556edbe1acf4210f7c624bb25e66a8ad06d780b 100644 --- a/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.cpp +++ b/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.cpp @@ -818,6 +818,12 @@ void MenuWrapperPattern::ClearAllSubMenu() } } +bool PreviewBorderRadiusHasPositive(const BorderRadiusProperty& borderRadius) +{ + return borderRadius.radiusTopLeft->IsValid() || borderRadius.radiusTopRight->IsValid() || + borderRadius.radiusBottomLeft->IsValid() || borderRadius.radiusBottomRight->IsValid(); +} + void MenuWrapperPattern::StopPreviewMenuAnimation() { if (HasTransitionEffect() || HasPreviewTransitionEffect()) { @@ -871,8 +877,8 @@ void MenuWrapperPattern::StopPreviewMenuAnimation() if (previewScaleContext && Positive(animationInfo.previewScale)) { previewScaleContext->UpdateTransformScale(VectorF(animationInfo.previewScale, animationInfo.previewScale)); - if (Positive(animationInfo.borderRadius)) { - previewScaleContext->UpdateBorderRadius(BorderRadiusProperty(Dimension(animationInfo.borderRadius))); + if (PreviewBorderRadiusHasPositive(animationInfo.borderRadius)) { + previewScaleContext->UpdateBorderRadius(animationInfo.borderRadius); } } }); diff --git a/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h b/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h index 03b10836faaa96b6d8e8d1aeee894eced7f274bd..d87fafb47a1850717060549a1580496baa1cede8 100644 --- a/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h +++ b/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h @@ -485,9 +485,12 @@ public: animationInfo_.clipRate = rate; } - void SetAnimationBorderRadius(float radius) + void SetAnimationBorderRadius(double rate, const BorderRadiusProperty& radius) { - animationInfo_.borderRadius = radius; + animationInfo_.borderRadius.radiusTopLeft = Dimension(radius.radiusTopLeft->Value() * rate); + animationInfo_.borderRadius.radiusTopRight = Dimension(radius.radiusTopRight->Value() * rate); + animationInfo_.borderRadius.radiusBottomLeft = Dimension(radius.radiusBottomLeft->Value() * rate); + animationInfo_.borderRadius.radiusBottomRight = Dimension(radius.radiusBottomRight->Value() * rate); } PreviewMenuAnimationInfo GetPreviewMenuAnimationInfo()