From 880c61c9bc24a521571f2cbc7d7598933dedf849 Mon Sep 17 00:00:00 2001 From: wangxiuxiu96 Date: Wed, 19 Mar 2025 17:07:02 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E4=B8=8E=E6=8B=96=E6=8B=BD?= =?UTF-8?q?=E8=BF=87=E6=B8=A1=EF=BC=8C=E8=8F=9C=E5=8D=95=E8=B7=9F=E9=9A=8F?= =?UTF-8?q?=E6=95=88=E6=9E=9C=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangxiuxiu96 Change-Id: I2b1335f42e919d7f795c70de064b4463b5400298 --- .../components_ng/event/gesture_event_hub.h | 17 +- .../event/gesture_event_hub_drag.cpp | 60 ++++- .../manager/drag_drop/drag_drop_manager.cpp | 16 +- .../drag_drop/utils/drag_animation_helper.cpp | 17 ++ .../drag_drop/utils/drag_animation_helper.h | 1 + .../pattern/menu/menu_pattern.cpp | 60 +++++ .../components_ng/pattern/menu/menu_pattern.h | 2 + .../components_ng/pattern/menu/menu_view.cpp | 214 ++++++++++++++++++ .../components_ng/pattern/menu/menu_view.h | 15 ++ 9 files changed, 391 insertions(+), 11 deletions(-) diff --git a/frameworks/core/components_ng/event/gesture_event_hub.h b/frameworks/core/components_ng/event/gesture_event_hub.h index ed62a4c477b..b16fdf84c6b 100644 --- a/frameworks/core/components_ng/event/gesture_event_hub.h +++ b/frameworks/core/components_ng/event/gesture_event_hub.h @@ -37,6 +37,7 @@ #include "core/components_ng/manager/drag_drop/drag_drop_proxy.h" #include "core/event/pointer_event.h" #include "core/gestures/gesture_info.h" +#include "core/components/common/properties/placement.h" namespace OHOS::Ace { struct DragNotifyMsg; @@ -95,6 +96,17 @@ struct PreparedInfoForDrag { RefPtr menuPreviewNode { nullptr }; RefPtr textRowNode { nullptr }; RefPtr gatherNode { nullptr }; + RefPtr menuNode { nullptr }; + bool hasTransition = false; + // for menu follow animation + float menuPositionLeft = 0.0f; + float menuPositionTop = 0.0f; + float menuPositionRight = 0.0f; + float menuPositionBottom = 0.0f; + // for menu follow animations + Placement menuPosition = Placement::NONE; + RectF menuRect; + RectF frameNodeRect; RectF menuPreviewRect; RectF dragPreviewRect; BorderRadiusProperty borderRadius = BorderRadiusProperty(0.0_vp); @@ -381,7 +393,10 @@ private: void OnDragStart(const GestureEvent& info, const RefPtr& context, const RefPtr frameNode, DragDropInfo dragDropInfo, const RefPtr& dragEvent); - void PrepareDragStartInfo(RefPtr& pipeline, PreparedInfoForDrag& data); + void PrepareDragStartInfo( + RefPtr& pipeline, PreparedInfoForDrag& data, const RefPtr frameNode); + void UpdateMenuNode( + const RefPtr menuWrapperNode, PreparedInfoForDrag& data, const RefPtr frameNode); void StartVibratorByDrag(const RefPtr& frameNode); void UpdateExtraInfo(const RefPtr& frameNode, std::unique_ptr& arkExtraInfoJson, float scale, const PreparedInfoForDrag& dragInfoData); diff --git a/frameworks/core/components_ng/event/gesture_event_hub_drag.cpp b/frameworks/core/components_ng/event/gesture_event_hub_drag.cpp index 91c2f682c52..bb3143884fe 100644 --- a/frameworks/core/components_ng/event/gesture_event_hub_drag.cpp +++ b/frameworks/core/components_ng/event/gesture_event_hub_drag.cpp @@ -801,7 +801,8 @@ void CalcPreviewPaintRect(const RefPtr menuWrapperNode, PreparedInfoF data.borderRadius = animationInfo.borderRadius; } -void GestureEventHub::PrepareDragStartInfo(RefPtr& pipeline, PreparedInfoForDrag& data) +void GestureEventHub::PrepareDragStartInfo( + RefPtr& pipeline, PreparedInfoForDrag& data, const RefPtr frameNode) { CHECK_NULL_VOID(pipeline); auto dragDropManager = pipeline->GetDragDropManager(); @@ -823,6 +824,11 @@ void GestureEventHub::PrepareDragStartInfo(RefPtr& pipeline, Pr auto relativeContainerRenderContext = relativeContainerNode->GetRenderContext(); CHECK_NULL_VOID(relativeContainerRenderContext); relativeContainerRenderContext->UpdateTransformTranslate({ 0, 0, 0.0f }); + CHECK_NULL_VOID(frameNode); + if (frameNode->GetDragPreviewOption().sizeChangeEffect != DraggingSizeChangeEffect::DEFAULT && + !data.hasTransition) { + GestureEventHub::UpdateMenuNode(menuWrapperNode, data, frameNode); + } } void GestureEventHub::OnDragStart(const GestureEvent& info, const RefPtr& context, @@ -920,7 +926,7 @@ void GestureEventHub::OnDragStart(const GestureEvent& info, const RefPtrResetContextMenuDragPosition(); RefPtr subWindow = nullptr; if (!needChangeFwkForLeaveWindow && IsNeedSwitchToSubWindow(data)) { - GestureEventHub::PrepareDragStartInfo(pipeline, data); + GestureEventHub::PrepareDragStartInfo(pipeline, data, frameNode); auto imageNode = overlayManager->GetPixelMapContentNode(); DragAnimationHelper::CreatePreviewNode(frameNode, imageNode, defaultPixelMapScale, data); CHECK_NULL_VOID(imageNode); @@ -1618,6 +1624,55 @@ OffsetF GestureEventHub::GetDragPreviewInitPositionToScreen( return previewOffset; } +void GestureEventHub::UpdateMenuNode( + const RefPtr menuWrapperNode, PreparedInfoForDrag& data, const RefPtr frameNode) +{ + CHECK_NULL_VOID(menuWrapperNode); + auto menuWrapperPattern = menuWrapperNode->GetPattern(); + CHECK_NULL_VOID(menuWrapperPattern); + data.hasTransition = menuWrapperPattern->HasTransitionEffect(); + if (data.hasTransition) { + return; + } + auto menuNode = menuWrapperPattern->GetMenu(); + CHECK_NULL_VOID(menuNode); + auto menuGeometryNode = menuNode->GetGeometryNode(); + CHECK_NULL_VOID(menuGeometryNode); + auto menuNodeSize = menuGeometryNode->GetFrameRect(); + RefPtr imageNode; + RectF imageNodeSize; + if (data.menuPreviewNode) { + imageNode = data.menuPreviewNode; + CHECK_NULL_VOID(imageNode); + imageNodeSize = data.menuPreviewRect; + data.frameNodeRect = imageNodeSize; + } else { + imageNode = frameNode; + CHECK_NULL_VOID(imageNode); + auto imageGeometryNode = imageNode->GetGeometryNode(); + CHECK_NULL_VOID(imageGeometryNode); + imageNodeSize = imageGeometryNode->GetFrameRect(); + data.frameNodeRect = imageNodeSize; + } + auto imageNodeOffset = imageNode->GetPaintRectOffset(false, true); + auto menuNodeOffset = menuNode->GetPaintRectOffset(false, true); + data.menuRect = menuNodeSize; + data.menuPositionLeft = menuNodeOffset.GetX() - imageNodeOffset.GetX(); + data.menuPositionTop = menuNodeOffset.GetY() - imageNodeOffset.GetY(); + data.menuPositionRight = + imageNodeOffset.GetX() + imageNodeSize.Width() - menuNodeOffset.GetX() - menuNodeSize.Width(); + data.menuPositionBottom = + imageNodeOffset.GetY() + imageNodeSize.Height() - menuNodeOffset.GetY() - menuNodeSize.Height(); + auto menuParam = menuWrapperPattern->GetMenuParam(); + auto menuPattern = menuNode->GetPattern(); + CHECK_NULL_VOID(menuPattern); + auto newMenuNode = menuPattern->DuplicateMenuNode(menuNode, menuParam); + CHECK_NULL_VOID(newMenuNode); + data.menuNode = newMenuNode; + auto placement = menuPattern->GetLastPlacement().value_or(Placement::NONE); + data.menuPosition = placement; +} + int32_t GestureEventHub::GetBadgeNumber(const RefPtr& unifiedData) { auto frameNode = GetFrameNode(); @@ -1699,6 +1754,7 @@ bool GestureEventHub::TryDoDragStartAnimation(const RefPtr& contex pipeline->FlushSyncGeometryNodeTasks(); overlayManager->RemovePixelMap(); DragAnimationHelper::ShowBadgeAnimation(textNode); + DragAnimationHelper::ShowMenuHideAnimation(data.imageNode, data); DragAnimationHelper::HideDragNodeCopy(overlayManager); dragDropManager->DoDragStartAnimation( diff --git a/frameworks/core/components_ng/manager/drag_drop/drag_drop_manager.cpp b/frameworks/core/components_ng/manager/drag_drop/drag_drop_manager.cpp index 7cbe94af4b1..27d2825ab38 100644 --- a/frameworks/core/components_ng/manager/drag_drop/drag_drop_manager.cpp +++ b/frameworks/core/components_ng/manager/drag_drop/drag_drop_manager.cpp @@ -2214,12 +2214,12 @@ void DragDropManager::DragMoveAnimation( AnimationUtils::Animate( option, [renderContext, localPoint = newOffset, info = info_, overlayManager, menuRenderContext, menuPosition]() { - if (menuRenderContext && !menuPosition.NonOffset()) { - menuRenderContext->UpdatePosition( - OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); - } if (info.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT || !info.isMenuShow) { + if (menuRenderContext && !menuPosition.NonOffset()) { + menuRenderContext->UpdatePosition( + OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); + } renderContext->UpdateTransformTranslate({ localPoint.GetX(), localPoint.GetY(), 0.0f }); UpdateGatherNodePosition(overlayManager, info.imageNode); } @@ -2326,12 +2326,12 @@ void DragDropManager::DragStartAnimation(const Offset& newOffset, const RefPtrUpdatePosition( - OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); - } if (data.imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT || !info.isMenuShow) { + if (menuRenderContext && !menuPosition.NonOffset()) { + menuRenderContext->UpdatePosition( + OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); + } HandleDragPreviewUpdate(renderContext, info, newOffset, overlayManager); } GatherAnimationInfo gatherAnimationInfo = { info.scale, info.width, info.height, gatherNodeCenter, diff --git a/frameworks/core/components_ng/manager/drag_drop/utils/drag_animation_helper.cpp b/frameworks/core/components_ng/manager/drag_drop/utils/drag_animation_helper.cpp index 02db26c273e..3a445ed064e 100644 --- a/frameworks/core/components_ng/manager/drag_drop/utils/drag_animation_helper.cpp +++ b/frameworks/core/components_ng/manager/drag_drop/utils/drag_animation_helper.cpp @@ -18,6 +18,7 @@ #include "core/components_ng/manager/drag_drop/drag_drop_controller_func_wrapper.h" #include "core/components_ng/pattern/image/image_pattern.h" #include "core/components_ng/pattern/menu/menu_theme.h" +#include "core/components_ng/pattern/menu/menu_view.h" #include "core/components_ng/pattern/menu/preview/menu_preview_pattern.h" #include "core/components_ng/pattern/relative_container/relative_container_pattern.h" #include "core/components_ng/pattern/stack/stack_pattern.h" @@ -270,6 +271,17 @@ void DragAnimationHelper::PlayGatherAnimation(const RefPtr& frameNode option.GetOnFinishEvent()); } +void DragAnimationHelper::ShowMenuHideAnimation(const RefPtr& imageNode, const PreparedInfoForDrag& data) +{ + CHECK_NULL_VOID(imageNode); + if (imageNode->GetDragPreviewOption().sizeChangeEffect == DraggingSizeChangeEffect::DEFAULT || data.hasTransition) { + return; + } + auto menuNode = data.menuNode; + CHECK_NULL_VOID(menuNode); + MenuView::ExcuteMenuDisappearAnimation(menuNode, data); +} + void DragAnimationHelper::ShowBadgeAnimation(const RefPtr& textNode) { auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck(); @@ -1127,6 +1139,11 @@ void DragAnimationHelper::MountPixelMapSizeContentTransition( if (data.textRowNode) { data.relativeContainerNode->AddChild(data.textRowNode); } + if (data.menuNode) { + auto menuNode = data.menuNode; + MenuView::UpdateMenuNodePosition(data); + data.relativeContainerNode->AddChild(data.menuNode); + } } void DragAnimationHelper::CreateAndMountMenuPreviewNode( diff --git a/frameworks/core/components_ng/manager/drag_drop/utils/drag_animation_helper.h b/frameworks/core/components_ng/manager/drag_drop/utils/drag_animation_helper.h index 0833ec310e1..63ff6f34bc5 100644 --- a/frameworks/core/components_ng/manager/drag_drop/utils/drag_animation_helper.h +++ b/frameworks/core/components_ng/manager/drag_drop/utils/drag_animation_helper.h @@ -45,6 +45,7 @@ public: static void PlayNodeResetAnimation(const RefPtr& actuator); static void PlayGatherAnimation(const RefPtr& frameNode, const RefPtr& overlayManager); static void ShowBadgeAnimation(const RefPtr& textNode); + static void ShowMenuHideAnimation(const RefPtr& imageNode, const PreparedInfoForDrag& data); static void CalcBadgeTextPosition(const RefPtr& menuPattern, const RefPtr& manager, const RefPtr& imageNode, const RefPtr& textNode); static OffsetF CalcBadgeTextOffset(const RefPtr& menuPattern, const RefPtr& imageNode, diff --git a/frameworks/core/components_ng/pattern/menu/menu_pattern.cpp b/frameworks/core/components_ng/pattern/menu/menu_pattern.cpp index 36f4ace90e9..8c04c661f77 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_pattern.cpp +++ b/frameworks/core/components_ng/pattern/menu/menu_pattern.cpp @@ -1228,6 +1228,66 @@ Offset MenuPattern::GetTransformCenter() const } } +RefPtr MenuPattern::DuplicateMenuNode(const RefPtr& menuNode, const MenuParam& menuParam) +{ + auto duplicateMenuNode = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), + AceType::MakeRefPtr(false)); + CHECK_NULL_RETURN(menuNode, duplicateMenuNode); + auto menuLayoutProperty = menuNode->GetLayoutProperty(); + CHECK_NULL_RETURN(menuLayoutProperty, duplicateMenuNode); + auto scrollNode = AceType::DynamicCast(menuNode->GetChildByIndex(0)); + CHECK_NULL_RETURN(scrollNode, duplicateMenuNode); + auto menuUINode = scrollNode->GetParent(); + CHECK_NULL_RETURN(menuUINode, duplicateMenuNode); + menuUINode->RemoveChild(scrollNode); + menuUINode->RebuildRenderContextTree(); + menuUINode->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST); + duplicateMenuNode->AddChild(scrollNode); + if (menuLayoutProperty->GetBorderRadius().has_value()) { + BorderRadiusProperty borderRadius = menuLayoutProperty->GetBorderRadiusValue(); + UpdateBorderRadius(duplicateMenuNode, borderRadius); + } + SetMenuBackGroundStyle(duplicateMenuNode, menuParam); + return duplicateMenuNode; +} + +void MenuPattern::SetMenuBackGroundStyle(const RefPtr& menuNode, const MenuParam& menuParam) +{ + CHECK_NULL_VOID(menuNode); + auto renderContext = menuNode->GetRenderContext(); + CHECK_NULL_VOID(renderContext); + BlurStyleOption styleOption; + if (menuParam.backgroundColor.has_value()) { + styleOption.blurStyle = BlurStyle::NO_MATERIAL; + renderContext->UpdateBackgroundColor(menuParam.backgroundColor.value_or(Color::TRANSPARENT)); + } else { + styleOption.blurStyle = static_cast( + menuParam.backgroundBlurStyle.value_or(static_cast(BlurStyle::COMPONENT_ULTRA_THICK))); + renderContext->UpdateBackgroundColor(Color::TRANSPARENT); + } + renderContext->UpdateBackBlurStyle(styleOption); + if (menuParam.backgroundBlurStyleOption.has_value()) { + BlurStyleOption backgroundBlurStyleOption = menuParam.backgroundBlurStyleOption.value(); + if (renderContext->GetBackgroundEffect().has_value()) { + renderContext->UpdateBackgroundEffect(std::nullopt); + } + renderContext->UpdateBackBlurStyle(backgroundBlurStyleOption); + if (renderContext->GetBackBlurRadius().has_value()) { + renderContext->UpdateBackBlurRadius(Dimension()); + } + } + if (menuParam.backgroundEffectOption.has_value()) { + EffectOption backgroundEffectOption = menuParam.backgroundEffectOption.value(); + if (renderContext->GetBackBlurRadius().has_value()) { + renderContext->UpdateBackBlurRadius(Dimension()); + } + if (renderContext->GetBackBlurStyle().has_value()) { + renderContext->UpdateBackBlurStyle(std::nullopt); + } + renderContext->UpdateBackgroundEffect(backgroundEffectOption); + } +} + void MenuPattern::ShowPreviewPositionAnimation(AnimationOption& option, int32_t delay) { auto menuWrapper = GetMenuWrapper(); diff --git a/frameworks/core/components_ng/pattern/menu/menu_pattern.h b/frameworks/core/components_ng/pattern/menu/menu_pattern.h index 00c5f27cfd1..40260c291f6 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_pattern.h +++ b/frameworks/core/components_ng/pattern/menu/menu_pattern.h @@ -312,6 +312,7 @@ public: void MountOption(const RefPtr& option); void RemoveOption(); + RefPtr DuplicateMenuNode(const RefPtr& menuNode, const MenuParam& menuParam); RefPtr GetMenuColumn() const; @@ -683,6 +684,7 @@ private: RefPtr GetIfElseMenuItem(const RefPtr& parent, bool next); void HandleNextPressed(const RefPtr& parent, int32_t index, bool press, bool hover); void HandlePrevPressed(const RefPtr& parent, int32_t index, bool press); + void SetMenuBackGroundStyle(const RefPtr& menuNode, const MenuParam& menuParam); void UpdateMenuBorderAndBackgroundBlur() { auto host = GetHost(); diff --git a/frameworks/core/components_ng/pattern/menu/menu_view.cpp b/frameworks/core/components_ng/pattern/menu/menu_view.cpp index 7c6afea555f..416f6bcd5f8 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_view.cpp +++ b/frameworks/core/components_ng/pattern/menu/menu_view.cpp @@ -63,6 +63,9 @@ const RefPtr CUSTOM_PREVIEW_ANIMATION_CURVE = AceType::MakeRefPtr(0.0f, 1.0f, 380.0f, 34.0f); const std::string HOVER_IMAGE_CLIP_PROPERTY_NAME = "hoverImageClip"; constexpr float MIN_HOVER_SCALE_DIFF = 0.0001f; +constexpr int32_t HALF_NUMBER = 2; +constexpr int32_t HALF_NUMBER_NEGATIVE = -2; +constexpr int32_t MENU_ANIMATION_DURATION = 300; void MountTextNode(const RefPtr& wrapperNode, const RefPtr& previewCustomNode = nullptr) { @@ -1843,6 +1846,69 @@ RefPtr MenuView::CreateSelectOption(const SelectParam& param, int32_t return option; } +void MenuView::ExcuteMenuDisappearAnimation(const RefPtr& menuNode, const PreparedInfoForDrag& data) +{ + CHECK_NULL_VOID(menuNode); + RefPtr menuOpacityCurve = AceType::MakeRefPtr(0.2f, 0.0f, 0.2f, 1.0f); + RefPtr menuScaleCurve = AceType::MakeRefPtr(0.4f, 0.0f, 1.0f, 1.0f); + AnimationOption optionOpacity; + AnimationOption optionScale; + optionOpacity.SetCurve(menuOpacityCurve); + optionOpacity.SetDuration(MENU_ANIMATION_DURATION); + optionScale.SetCurve(menuScaleCurve); + optionScale.SetDuration(MENU_ANIMATION_DURATION); + auto menuNodeRenderContext = menuNode->GetRenderContext(); + CHECK_NULL_VOID(menuNodeRenderContext); + menuNodeRenderContext->UpdateOpacity(1.0f); + menuNodeRenderContext->UpdateTransformScale({ 0.95f, 0.95f }); + AnimationUtils::Animate( + optionOpacity, [menuNodeRenderContext]() { menuNodeRenderContext->UpdateOpacity(0.0f); }, + optionOpacity.GetOnFinishEvent()); + AnimationUtils::Animate( + optionScale, [menuNode, data]() { UpdateMenuNodeByAnimation(menuNode, data); }, optionScale.GetOnFinishEvent()); +} + +// update the alignment rules according to the positional relationship between the menu and the menu preview. +void MenuView::UpdateMenuNodePosition(const PreparedInfoForDrag& data) +{ + auto relativeContainerNode = data.relativeContainerNode; + CHECK_NULL_VOID(relativeContainerNode); + auto stackNode = AceType::DynamicCast(relativeContainerNode->GetChildByIndex(0)); + CHECK_NULL_VOID(stackNode); + stackNode->UpdateInspectorId("__stack__"); + auto menuNode = data.menuNode; + CHECK_NULL_VOID(menuNode); + auto menuNodeLayoutProperty = menuNode->GetLayoutProperty(); + CHECK_NULL_VOID(menuNodeLayoutProperty); + auto biasMenuLeft = (data.menuPositionLeft - data.menuPositionRight) / HALF_NUMBER; + auto biasMenuTop = (data.menuPositionTop - data.menuPositionBottom) / HALF_NUMBER; + MarginProperty menuNodeMargin; + std::map menuNodeAlignRules; + std::map alignMap = { { "top", { .anchor = "__stack__", .vertical = VerticalAlign::TOP } }, + { "center", { .anchor = "__stack__", .vertical = VerticalAlign::CENTER } }, + { "bottom", { .anchor = "__stack__", .vertical = VerticalAlign::BOTTOM } }, + { "start", { .anchor = "__stack__", .horizontal = HorizontalAlign::START } }, + { "middle", { .anchor = "__stack__", .horizontal = HorizontalAlign::CENTER } }, + { "end", { .anchor = "__stack__", .horizontal = HorizontalAlign::END } } }; + if (data.menuPosition == Placement::TOP_LEFT || data.menuPosition == Placement::BOTTOM_LEFT || + data.menuPosition == Placement::TOP || data.menuPosition == Placement::BOTTOM || + data.menuPosition == Placement::TOP_RIGHT || data.menuPosition == Placement::BOTTOM_RIGHT) { + // when the menu appears at the top or bottom of the menu preview, the top or bottom of the menu needs to be + // anchored to the bottom or top of the menu preview. + UpdateMenuNodePositionTop(menuNodeMargin, menuNodeAlignRules, data, biasMenuLeft, alignMap); + menuNodeLayoutProperty->UpdateAlignRules(menuNodeAlignRules); + } else if (data.menuPosition == Placement::LEFT_TOP || data.menuPosition == Placement::RIGHT_TOP || + data.menuPosition == Placement::LEFT || data.menuPosition == Placement::RIGHT || + data.menuPosition == Placement::LEFT_BOTTOM || data.menuPosition == Placement::RIGHT_BOTTOM) { + // when the menu appears on the left or right side of the menu preview, the left or right side of the menu needs + // to be anchored to the left or right side of the menu preview. + UpdateMenuNodePositionLeft(menuNodeMargin, menuNodeAlignRules, data, biasMenuTop, alignMap); + menuNodeLayoutProperty->UpdateAlignRules(menuNodeAlignRules); + } + menuNodeLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT); + menuNodeLayoutProperty->UpdateMargin(menuNodeMargin); +} + RefPtr MenuView::Create(int32_t index) { auto Id = ElementRegister::GetInstance()->MakeUniqueId(); @@ -1879,4 +1945,152 @@ RefPtr MenuView::Create(int32_t index) layoutProp->UpdateMargin(margin); return node; } + +// if the menu is at the top of the menu preview, then both the top and the bottom of the menu will be aligned with the +// top of the menu preview. Conversely, if it is in other situations, they will be aligned with the bottom. +void MenuView::UpdateMenuPositionTop(MarginProperty& menuNodeMargin, + std::map& menuNodeAlignRules, AlignRule& alignMap, float biasMenuTop, + float biasMenuBottom) +{ + menuNodeAlignRules[AlignDirection::TOP] = alignMap; + menuNodeAlignRules[AlignDirection::BOTTOM] = alignMap; + menuNodeMargin.top = CalcLength(Dimension(biasMenuTop)); + menuNodeMargin.bottom = CalcLength(Dimension(biasMenuBottom)); +} + +// if the menu is on the left side of the menu preview, then both the left and the right sides of the menu will be +// aligned with the left side of the menu preview. Conversely, they will be aligned with the right side. +void MenuView::UpdateMenuPositionLeft(MarginProperty& menuNodeMargin, + std::map& menuNodeAlignRules, AlignRule& alignMap, float biasMenuLeft, + float biasMenuRight) +{ + menuNodeAlignRules[AlignDirection::LEFT] = alignMap; + menuNodeAlignRules[AlignDirection::RIGHT] = alignMap; + menuNodeMargin.left = CalcLength(Dimension(biasMenuLeft)); + menuNodeMargin.right = CalcLength(Dimension(biasMenuRight)); +} + +// if the menu is at the top or bottom of the menu preview, then the left and right sides of the menu will adjust the +// anchoring rules according to the position where the menu appears. +void MenuView::UpdateMenuNodePositionTop(MarginProperty& menuNodeMargin, + std::map& menuNodeAlignRules, const PreparedInfoForDrag& data, float biasMenuLeft, + std::map& alignMap) +{ + if (data.menuPosition == Placement::BOTTOM_LEFT || data.menuPosition == Placement::BOTTOM || + data.menuPosition == Placement::BOTTOM_RIGHT) { + UpdateMenuPositionTop(menuNodeMargin, menuNodeAlignRules, alignMap["bottom"], + data.menuPositionTop - data.frameNodeRect.Height(), data.menuPositionBottom); + } else { + UpdateMenuPositionTop(menuNodeMargin, menuNodeAlignRules, alignMap["top"], data.menuPositionTop, + data.menuPositionBottom - data.frameNodeRect.Height()); + } + switch (data.menuPosition) { + case Placement::BOTTOM_LEFT: + UpdateMenuPositionLeft(menuNodeMargin, menuNodeAlignRules, alignMap["start"], data.menuPositionLeft, + (-1) * data.menuPositionLeft - data.menuRect.Width()); + break; + case Placement::BOTTOM: + UpdateMenuPositionLeft(menuNodeMargin, menuNodeAlignRules, alignMap["middle"], + (data.menuRect.Width() / HALF_NUMBER_NEGATIVE) + biasMenuLeft, + (data.menuRect.Width() / HALF_NUMBER_NEGATIVE) - biasMenuLeft); + break; + case Placement::BOTTOM_RIGHT: + UpdateMenuPositionLeft(menuNodeMargin, menuNodeAlignRules, alignMap["end"], + (-1) * data.menuPositionRight - data.menuRect.Width(), data.menuPositionRight); + break; + case Placement::TOP_LEFT: + UpdateMenuPositionLeft(menuNodeMargin, menuNodeAlignRules, alignMap["start"], data.menuPositionLeft, + (-1) * data.menuPositionLeft - data.menuRect.Width()); + break; + case Placement::TOP: + UpdateMenuPositionLeft(menuNodeMargin, menuNodeAlignRules, alignMap["middle"], + (data.menuRect.Width() / HALF_NUMBER_NEGATIVE) + biasMenuLeft, + (data.menuRect.Width() / HALF_NUMBER_NEGATIVE) - biasMenuLeft); + break; + case Placement::TOP_RIGHT: + UpdateMenuPositionLeft(menuNodeMargin, menuNodeAlignRules, alignMap["end"], + (-1) * data.menuPositionRight - data.menuRect.Width(), data.menuPositionRight); + break; + default: + break; + } +} + +// if the menu is on the left or right side of the menu preview, then the top and bottom of the menu will adjust the +// anchoring rules according to the position where the menu appears. +void MenuView::UpdateMenuNodePositionLeft(MarginProperty& menuNodeMargin, + std::map& menuNodeAlignRules, const PreparedInfoForDrag& data, float biasMenuTop, + std::map& alignMap) +{ + if (data.menuPosition == Placement::LEFT_TOP || data.menuPosition == Placement::LEFT || + data.menuPosition == Placement::LEFT_BOTTOM) { + UpdateMenuPositionLeft(menuNodeMargin, menuNodeAlignRules, alignMap["start"], data.menuPositionLeft, + data.menuPositionRight - data.frameNodeRect.Width()); + } else { + UpdateMenuPositionLeft(menuNodeMargin, menuNodeAlignRules, alignMap["end"], + data.menuPositionLeft - data.frameNodeRect.Width(), data.menuPositionRight); + } + switch (data.menuPosition) { + case Placement::LEFT_TOP: + UpdateMenuPositionTop(menuNodeMargin, menuNodeAlignRules, alignMap["top"], data.menuPositionTop, + (-1) * data.menuPositionTop - data.menuRect.Height()); + break; + case Placement::LEFT: + UpdateMenuPositionTop(menuNodeMargin, menuNodeAlignRules, alignMap["center"], + (data.menuRect.Height() / HALF_NUMBER_NEGATIVE) + biasMenuTop, + (data.menuRect.Height() / HALF_NUMBER_NEGATIVE) - biasMenuTop); + break; + case Placement::LEFT_BOTTOM: + UpdateMenuPositionTop(menuNodeMargin, menuNodeAlignRules, alignMap["bottom"], + (-1) * data.menuPositionBottom - data.menuRect.Height(), data.menuPositionBottom); + break; + case Placement::RIGHT_TOP: + UpdateMenuPositionTop(menuNodeMargin, menuNodeAlignRules, alignMap["top"], data.menuPositionTop, + (-1) * data.menuPositionTop - data.menuRect.Height()); + break; + case Placement::RIGHT: + UpdateMenuPositionTop(menuNodeMargin, menuNodeAlignRules, alignMap["center"], + (data.menuRect.Height() / HALF_NUMBER_NEGATIVE) + biasMenuTop, + (data.menuRect.Height() / HALF_NUMBER_NEGATIVE) - biasMenuTop); + break; + case Placement::RIGHT_BOTTOM: + UpdateMenuPositionTop(menuNodeMargin, menuNodeAlignRules, alignMap["bottom"], + (-1) * data.menuPositionBottom - data.menuRect.Height(), data.menuPositionBottom); + break; + default: + break; + } +} + +// Update the animation indentation point according to the position where the menu appears. +void MenuView::UpdateMenuNodeByAnimation(const RefPtr& menuNode, const PreparedInfoForDrag& data) +{ + CHECK_NULL_VOID(menuNode); + auto menuNodeRenderContext = menuNode->GetRenderContext(); + CHECK_NULL_VOID(menuNodeRenderContext); + auto menuRect = data.menuRect; + auto menuWidth = menuRect.Width(); + auto menuHeight = menuRect.Height(); + auto biasMenuLeft = (data.menuPositionLeft - data.menuPositionRight) / HALF_NUMBER; + auto biasMenuTop = (data.menuPositionTop - data.menuPositionBottom) / HALF_NUMBER; + double x = 0.0; + double y = 0.0; + Placement placement = data.menuPosition; + if (placement == Placement::LEFT_TOP || placement == Placement::LEFT || placement == Placement::LEFT_BOTTOM) { + x = menuWidth; + } else if (placement == Placement::BOTTOM || placement == Placement::TOP) { + x = (menuWidth / HALF_NUMBER) - biasMenuLeft; + } else if (placement == Placement::BOTTOM_RIGHT || placement == Placement::TOP_RIGHT) { + x = menuWidth; + } + if (placement == Placement::TOP_LEFT || placement == Placement::TOP || placement == Placement::TOP_RIGHT) { + y = menuHeight; + } else if (placement == Placement::LEFT || placement == Placement::RIGHT) { + y = (menuHeight / HALF_NUMBER) - biasMenuTop; + } else if (placement == Placement::LEFT_BOTTOM || placement == Placement::RIGHT_BOTTOM) { + y = menuHeight; + } + menuNodeRenderContext->UpdateTransformCenter(DimensionOffset(Offset(x, y))); + menuNodeRenderContext->UpdateTransformScale({ 0.4f, 0.4f }); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/menu/menu_view.h b/frameworks/core/components_ng/pattern/menu/menu_view.h index 3fdf3dde086..b04ccb0e61d 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_view.h +++ b/frameworks/core/components_ng/pattern/menu/menu_view.h @@ -70,6 +70,8 @@ public: static RefPtr CreateSymbol(const std::function)>& symbol, const RefPtr& parent, const RefPtr& child = nullptr, const std::optional& symbolUserDefinedIdealFontSize = std::nullopt); + static void UpdateMenuNodePosition(const PreparedInfoForDrag& data); + static void ExcuteMenuDisappearAnimation(const RefPtr& menuNode, const PreparedInfoForDrag& data); private: static void UpdateMenuPaintProperty( @@ -93,6 +95,19 @@ private: static void MountOptionToColumn(std::vector& params, const RefPtr& menuNode, const MenuParam& menuParam, RefPtr column); static void UpdateMenuBackgroundStyleSub(const RefPtr& menuNode, const MenuParam& menuParam); + static void UpdateMenuNodeByAnimation(const RefPtr& menuNode, const PreparedInfoForDrag& data); + static void UpdateMenuPositionTop(MarginProperty& menuNodeMargin, + std::map& menuNodeAlignRules, AlignRule& alignMap, float biasMenuTop, + float biasMenuBottom); + static void UpdateMenuPositionLeft(MarginProperty& menuNodeMargin, + std::map& menuNodeAlignRules, AlignRule& alignMap, float biasMenuLeft, + float biasMenuRight); + static void UpdateMenuNodePositionTop(MarginProperty& menuNodeMargin, + std::map& menuNodeAlignRules, const PreparedInfoForDrag& data, float biasMenuLeft, + std::map& alignMap); + static void UpdateMenuNodePositionLeft(MarginProperty& menuNodeMargin, + std::map& menuNodeAlignRules, const PreparedInfoForDrag& data, float biasMenuLeft, + std::map& alignMap); }; } // namespace OHOS::Ace::NG -- Gitee