From 395cc8924a471ea5bb72573d3442702ad971eaf2 Mon Sep 17 00:00:00 2001 From: Flanif Date: Sun, 19 May 2024 23:22:25 +0800 Subject: [PATCH] =?UTF-8?q?contextMenu=E9=A2=84=E8=A7=88=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=9C=BA=E6=99=AF=E9=95=BF=E6=8C=89=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E6=8B=96=E6=8B=BD=E9=A2=84=E8=A7=88=E5=9B=BE=E8=BF=87=E6=B8=A1?= =?UTF-8?q?=E5=8A=A8=E6=95=88=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Flanif --- .../jsview/js_view_abstract.cpp | 20 +- .../base/view_abstract_model_ng.cpp | 2 +- .../core/components_ng/event/drag_event.cpp | 1 + .../pattern/menu/menu_pattern.cpp | 120 +++++--- .../components_ng/pattern/menu/menu_pattern.h | 33 ++ .../components_ng/pattern/menu/menu_theme.h | 40 +++ .../components_ng/pattern/menu/menu_view.cpp | 286 +++++++++++++----- .../menu/preview/menu_preview_pattern.cpp | 121 ++++++-- .../menu/preview/menu_preview_pattern.h | 92 ++++++ .../menu/wrapper/menu_wrapper_pattern.h | 32 ++ .../pattern/overlay/overlay_manager.cpp | 146 ++++++--- .../components_ng/property/menu_property.h | 2 + 12 files changed, 708 insertions(+), 187 deletions(-) diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index 5c37cee5ebd..b455cd2325f 100755 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -3346,19 +3346,19 @@ void ParseBindOptionParam(const JSCallbackInfo& info, NG::MenuParam& menuParam, ParseMenuParam(info, menuOptions, menuParam); } -void ParseAnimationScaleArray(const JSRef& scaleArray, NG::MenuParam& menuParam) +void ParseAnimationScaleArray(const JSRef& scaleArray, MenuPreviewAnimationOptions& options) { constexpr int scaleArraySize = 2; if (scaleArray->Length() == scaleArraySize) { auto scalePropertyFrom = scaleArray->GetValueAt(0); if (scalePropertyFrom->IsNumber()) { auto scaleFrom = scalePropertyFrom->ToNumber(); - menuParam.previewAnimationOptions.scaleFrom = LessOrEqual(scaleFrom, 0.0) ? -1.0f : scaleFrom; + options.scaleFrom = LessOrEqual(scaleFrom, 0.0) ? -1.0f : scaleFrom; } auto scalePropertyTo = scaleArray->GetValueAt(1); if (scalePropertyTo->IsNumber()) { auto scaleTo = scalePropertyTo->ToNumber(); - menuParam.previewAnimationOptions.scaleTo = LessOrEqual(scaleTo, 0.0) ? -1.0f : scaleTo; + options.scaleTo = LessOrEqual(scaleTo, 0.0) ? -1.0f : scaleTo; } } } @@ -3375,7 +3375,7 @@ void ParseContentPreviewAnimationOptionsParam(const JSCallbackInfo& info, const auto scaleProperty = animationOptionsObj->GetProperty("scale"); if (!scaleProperty->IsEmpty() && scaleProperty->IsArray()) { JSRef scaleArray = JSRef::Cast(scaleProperty); - ParseAnimationScaleArray(scaleArray, menuParam); + ParseAnimationScaleArray(scaleArray, menuParam.previewAnimationOptions); } auto previewTransition = animationOptionsObj->GetProperty("transition"); menuParam.hasPreviewTransitionEffect = false; @@ -3384,6 +3384,18 @@ void ParseContentPreviewAnimationOptionsParam(const JSCallbackInfo& info, const menuParam.hasPreviewTransitionEffect = true; menuParam.previewTransition = ParseChainedTransition(obj, info.GetExecutionContext()); } + if (menuParam.previewMode != MenuPreviewMode::CUSTOM) { + return; + } + auto hoverScaleProperty = animationOptionsObj->GetProperty("hoverScale"); + menuParam.isShowHoverImage = false; + menuParam.hoverImageAnimationOptions.scaleFrom = -1.0f; + menuParam.hoverImageAnimationOptions.scaleTo = -1.0f; + if (!hoverScaleProperty->IsEmpty() && hoverScaleProperty->IsArray()) { + JSRef hoverScaleArray = JSRef::Cast(hoverScaleProperty); + ParseAnimationScaleArray(hoverScaleArray, menuParam.hoverImageAnimationOptions); + menuParam.isShowHoverImage = true; + } } } diff --git a/frameworks/core/components_ng/base/view_abstract_model_ng.cpp b/frameworks/core/components_ng/base/view_abstract_model_ng.cpp index 8d2d11e7f7b..b77f83aecfe 100644 --- a/frameworks/core/components_ng/base/view_abstract_model_ng.cpp +++ b/frameworks/core/components_ng/base/view_abstract_model_ng.cpp @@ -321,7 +321,7 @@ void ViewAbstractModelNG::BindContextMenu(ResponseType type, std::functionIsAboutToPreview() || dragDropManager->IsDragging()) { return; } - if (menuParam.previewMode == MenuPreviewMode::IMAGE) { + if (menuParam.previewMode == MenuPreviewMode::IMAGE || menuParam.isShowHoverImage) { auto context = targetNode->GetRenderContext(); CHECK_NULL_VOID(context); auto gestureHub = targetNode->GetEventHub()->GetGestureEventHub(); diff --git a/frameworks/core/components_ng/event/drag_event.cpp b/frameworks/core/components_ng/event/drag_event.cpp index 6aea8898b44..a261ac6e46e 100644 --- a/frameworks/core/components_ng/event/drag_event.cpp +++ b/frameworks/core/components_ng/event/drag_event.cpp @@ -1188,6 +1188,7 @@ void DragEventActuator::HidePixelMap(bool startDrag, double x, double y, bool sh manager->RemovePreviewBadgeNode(); manager->RemoveGatherNodeWithAnimation(); } + if (showAnimation) { manager->RemovePixelMapAnimation(startDrag, x, y); } else { diff --git a/frameworks/core/components_ng/pattern/menu/menu_pattern.cpp b/frameworks/core/components_ng/pattern/menu/menu_pattern.cpp index 0957b78afde..4289c98eff4 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_pattern.cpp +++ b/frameworks/core/components_ng/pattern/menu/menu_pattern.cpp @@ -155,7 +155,8 @@ void UpdateMenuItemTextNode(RefPtr& menuProperty, RefPtr& menuTheme, const RefPtr& renderContext) +void ShowMenuOpacityAnimation(const RefPtr& menuTheme, const RefPtr& renderContext, + int32_t delay) { CHECK_NULL_VOID(menuTheme); CHECK_NULL_VOID(renderContext); @@ -164,6 +165,7 @@ void ShowMenuOpacityAnimation(const RefPtr& menuTheme, const RefPtrGetContextMenuAppearDuration()); + option.SetDelay(delay); AnimationUtils::Animate(option, [renderContext]() { if (renderContext) { renderContext->UpdateOpacity(1.0); @@ -989,63 +991,83 @@ Offset MenuPattern::GetTransformCenter() const } } +void MenuPattern::ShowPreviewMenuScaleAnimation() +{ + auto menuWrapper = GetMenuWrapper(); + CHECK_NULL_VOID(menuWrapper); + auto menuWrapperPattern = menuWrapper->GetPattern(); + CHECK_NULL_VOID(menuWrapperPattern); + auto preview = menuWrapperPattern->GetPreview(); + CHECK_NULL_VOID(preview); + auto previewRenderContext = preview->GetRenderContext(); + CHECK_NULL_VOID(previewRenderContext); + auto previewGeometryNode = preview->GetGeometryNode(); + CHECK_NULL_VOID(previewGeometryNode); + auto previewPosition = previewGeometryNode->GetFrameOffset(); + OffsetF previewOriginPosition = GetPreviewOriginOffset(); + + auto pipeline = PipelineBase::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto menuTheme = pipeline->GetTheme(); + CHECK_NULL_VOID(menuTheme); + auto springMotionResponse = menuTheme->GetSpringMotionResponse(); + auto springMotionDampingFraction = menuTheme->GetSpringMotionDampingFraction(); + auto delay = isShowHoverImage_ && preview->GetTag() == V2::MENU_PREVIEW_ETS_TAG ? + menuTheme->GetHoverImageDelayDuration() : 0; + + previewRenderContext->UpdatePosition( + OffsetT(Dimension(previewOriginPosition.GetX()), Dimension(previewOriginPosition.GetY()))); + AnimationOption scaleOption = AnimationOption(); + auto motion = AceType::MakeRefPtr(springMotionResponse, springMotionDampingFraction); + scaleOption.SetCurve(motion); + scaleOption.SetDelay(delay); + AnimationUtils::Animate(scaleOption, [previewRenderContext, previewPosition]() { + if (previewRenderContext) { + previewRenderContext->UpdatePosition( + OffsetT(Dimension(previewPosition.GetX()), Dimension(previewPosition.GetY()))); + } + }); +} + void MenuPattern::ShowPreviewMenuAnimation() { + CHECK_NULL_VOID(isFirstShow_ && previewMode_ != MenuPreviewMode::NONE); + ShowPreviewMenuScaleAnimation(); + auto host = GetHost(); CHECK_NULL_VOID(host); - if (isFirstShow_ && previewMode_ != MenuPreviewMode::NONE) { - auto menuWrapper = GetMenuWrapper(); - CHECK_NULL_VOID(menuWrapper); - auto menuWrapperPattern = menuWrapper->GetPattern(); - CHECK_NULL_VOID(menuWrapperPattern); - auto preview = menuWrapperPattern->GetPreview(); - CHECK_NULL_VOID(preview); - auto previewRenderContext = preview->GetRenderContext(); - CHECK_NULL_VOID(previewRenderContext); - auto previewGeometryNode = preview->GetGeometryNode(); - CHECK_NULL_VOID(previewGeometryNode); - auto previewPosition = previewGeometryNode->GetFrameOffset(); - auto host = GetHost(); - CHECK_NULL_VOID(host); - auto renderContext = host->GetRenderContext(); - CHECK_NULL_VOID(renderContext); - renderContext->UpdateTransformCenter(DimensionOffset(GetTransformCenter())); - auto menuPosition = host->GetPaintRectOffset(); - OffsetF previewOriginPosition = GetPreviewOriginOffset(); - - auto pipeline = PipelineBase::GetCurrentContext(); - CHECK_NULL_VOID(pipeline); - auto menuTheme = pipeline->GetTheme(); - CHECK_NULL_VOID(menuTheme); - auto menuAnimationScale = menuTheme->GetMenuAnimationScale(); - auto springMotionResponse = menuTheme->GetSpringMotionResponse(); - auto springMotionDampingFraction = menuTheme->GetSpringMotionDampingFraction(); + auto renderContext = host->GetRenderContext(); + CHECK_NULL_VOID(renderContext); + renderContext->UpdateTransformCenter(DimensionOffset(GetTransformCenter())); + auto menuPosition = host->GetPaintRectOffset(); - renderContext->UpdateTransformScale(VectorF(menuAnimationScale, menuAnimationScale)); + auto pipeline = PipelineBase::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto menuTheme = pipeline->GetTheme(); + CHECK_NULL_VOID(menuTheme); + auto menuAnimationScale = menuTheme->GetMenuAnimationScale(); + auto springMotionResponse = menuTheme->GetSpringMotionResponse(); + auto springMotionDampingFraction = menuTheme->GetSpringMotionDampingFraction(); - previewRenderContext->UpdatePosition( - OffsetT(Dimension(previewOriginPosition.GetX()), Dimension(previewOriginPosition.GetY()))); - renderContext->UpdatePosition( - OffsetT(Dimension(originOffset_.GetX()), Dimension(originOffset_.GetY()))); + renderContext->UpdateTransformScale(VectorF(menuAnimationScale, menuAnimationScale)); - ShowMenuOpacityAnimation(menuTheme, renderContext); + renderContext->UpdatePosition( + OffsetT(Dimension(originOffset_.GetX()), Dimension(originOffset_.GetY()))); - AnimationOption scaleOption = AnimationOption(); - auto motion = AceType::MakeRefPtr(springMotionResponse, springMotionDampingFraction); - scaleOption.SetCurve(motion); - AnimationUtils::Animate(scaleOption, [renderContext, menuPosition, previewRenderContext, previewPosition]() { - if (renderContext) { - renderContext->UpdateTransformScale(VectorF(1.0f, 1.0f)); - renderContext->UpdatePosition( - OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); - } + auto delay = isShowHoverImage_ ? menuTheme->GetHoverImageDelayDuration() : 0; + ShowMenuOpacityAnimation(menuTheme, renderContext, delay); - if (previewRenderContext) { - previewRenderContext->UpdatePosition( - OffsetT(Dimension(previewPosition.GetX()), Dimension(previewPosition.GetY()))); - } - }); - } + AnimationOption scaleOption = AnimationOption(); + auto motion = AceType::MakeRefPtr(springMotionResponse, springMotionDampingFraction); + scaleOption.SetCurve(motion); + scaleOption.SetDelay(delay); + AnimationUtils::Animate(scaleOption, [renderContext, menuPosition]() { + if (renderContext) { + renderContext->UpdateTransformScale(VectorF(1.0f, 1.0f)); + renderContext->UpdatePosition( + OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); + } + }); isFirstShow_ = false; } diff --git a/frameworks/core/components_ng/pattern/menu/menu_pattern.h b/frameworks/core/components_ng/pattern/menu/menu_pattern.h index 5806a276f85..d8f0a75d167 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_pattern.h +++ b/frameworks/core/components_ng/pattern/menu/menu_pattern.h @@ -136,6 +136,36 @@ public: return previewAnimationOptions_.scaleTo; } + void SetIsShowHoverImage(bool isShow) + { + isShowHoverImage_ = isShow; + } + + bool GetIsShowHoverImage() const + { + return isShowHoverImage_; + } + + void SetHoverImageBeforeAnimationScale(float scaleBeforeAnimation) + { + hoverImageAnimationOptions_.scaleFrom = scaleBeforeAnimation; + } + + float GetHoverImageBeforeAnimationScale() const + { + return hoverImageAnimationOptions_.scaleFrom; + } + + void SetHoverImageAfterAnimationScale(float scaleAfterAnimation) + { + hoverImageAnimationOptions_.scaleTo = scaleAfterAnimation; + } + + float GetHoverImageAfterAnimationScale() const + { + return hoverImageAnimationOptions_.scaleTo; + } + bool IsNavigationMenu() const { return type_ == MenuType::NAVIGATION_MENU; @@ -448,6 +478,7 @@ private: Offset GetTransformCenter() const; void ShowPreviewMenuAnimation(); + void ShowPreviewMenuScaleAnimation(); void ShowMenuAppearAnimation(); void ShowStackExpandMenu(); void ShowArrowRotateAnimation() const; @@ -475,6 +506,8 @@ private: bool isSelectMenu_ = false; MenuPreviewMode previewMode_ = MenuPreviewMode::NONE; MenuPreviewAnimationOptions previewAnimationOptions_; + bool isShowHoverImage_ = false; + MenuPreviewAnimationOptions hoverImageAnimationOptions_; bool isFirstShow_ = false; bool isExtensionMenuShow_ = false; bool isSubMenuShow_ = false; diff --git a/frameworks/core/components_ng/pattern/menu/menu_theme.h b/frameworks/core/components_ng/pattern/menu/menu_theme.h index 0eca7690d4d..c6818457909 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_theme.h +++ b/frameworks/core/components_ng/pattern/menu/menu_theme.h @@ -28,6 +28,11 @@ constexpr uint8_t GRADIENT_END_GRADIENT = 255; constexpr uint32_t DEFAULT_BACKGROUND_COLOR = 0xFFFFFFF; constexpr uint32_t MENU_MIN_GRID_COUNTS = 2; constexpr uint32_t MENU_MAX_GRID_COUNTS = 6; +constexpr int32_t HOVER_IMAGE_OPACITY_CHANGE_DURATION = 150; +constexpr int32_t HOVER_IMAGE_DELAY_DURATION = 800; +constexpr int32_t HOVER_IMAGE_CUSTOM_PREVIEW_SCALE_DURATION = 650; +constexpr int32_t HOVER_IMAGE_PREVIEW_DISAPPEAR_DURATION = 450; +constexpr int32_t HOVER_IMAGE_DISAPPEAR_DURATION = 650; constexpr double OUTBORDER_RADIUS = 19.75; // Default value of outBorderRadius /** @@ -84,6 +89,11 @@ public: theme->borderColor_ = pattern->GetAttr("menu_border_color", Color::TRANSPARENT); theme->filterAnimationDuration_ = 250; theme->previewAnimationDuration_ = 300; + theme->hoverImageSwitchToPreviewOpacityDuration_ = HOVER_IMAGE_OPACITY_CHANGE_DURATION; + theme->hoverImageDelayDuration_ = HOVER_IMAGE_DELAY_DURATION; + theme->hoverImageCustomPreviewScaleDuration_ = HOVER_IMAGE_CUSTOM_PREVIEW_SCALE_DURATION; + theme->hoverImagePreviewDisappearDuration_ = HOVER_IMAGE_PREVIEW_DISAPPEAR_DURATION; + theme->hoverImageDisappearDuration_ = HOVER_IMAGE_DISAPPEAR_DURATION; theme->previewBeforeAnimationScale_ = 0.95f; theme->previewAfterAnimationScale_ = 1.1f; theme->menuAnimationScale_ = 0.4f; @@ -117,6 +127,31 @@ public: return previewAnimationDuration_; } + int32_t GetHoverImageSwitchToPreviewOpacityDuration() const + { + return hoverImageSwitchToPreviewOpacityDuration_; + } + + int32_t GetHoverImageDelayDuration() const + { + return hoverImageDelayDuration_; + } + + int32_t GetHoverImageCustomPreviewScaleDuration() const + { + return hoverImageCustomPreviewScaleDuration_; + } + + int32_t GetHoverImagePreviewDisAppearDuration() const + { + return hoverImagePreviewDisappearDuration_; + } + + int32_t GetHoverImageDisAppearDuration() const + { + return hoverImageDisappearDuration_; + } + float GetPreviewBeforeAnimationScale() const { return previewBeforeAnimationScale_; @@ -263,6 +298,11 @@ protected: private: int32_t filterAnimationDuration_ = 0; int32_t previewAnimationDuration_ = 0; + int32_t hoverImageSwitchToPreviewOpacityDuration_ = 0; + int32_t hoverImageDelayDuration_ = 0; + int32_t hoverImageCustomPreviewScaleDuration_ = 0; + int32_t hoverImagePreviewDisappearDuration_ = 0; + int32_t hoverImageDisappearDuration_ = 0; float previewBeforeAnimationScale_ = 1.0f; float previewAfterAnimationScale_ = 1.0f; float menuAnimationScale_ = 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 3f0574137b2..f666381c703 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_view.cpp +++ b/frameworks/core/components_ng/pattern/menu/menu_view.cpp @@ -53,6 +53,7 @@ namespace OHOS::Ace::NG { namespace { constexpr float PAN_MAX_VELOCITY = 2000.0f; +constexpr float HALF_DIVIDER_VALUE = 2.0f; void SetSelfAndChildDraggableFalse(const RefPtr& customNode) { @@ -70,10 +71,46 @@ void SetSelfAndChildDraggableFalse(const RefPtr& customNode) } } +void MountTextNode(const RefPtr& wrapperNode, const RefPtr& previewCustomNode = nullptr) +{ + CHECK_NULL_VOID(previewCustomNode); + auto pipeline = PipelineContext::GetMainPipelineContext(); + CHECK_NULL_VOID(pipeline); + auto manager = pipeline->GetOverlayManager(); + CHECK_NULL_VOID(manager); + auto gatherNode = manager->GetGatherNode(); + CHECK_NULL_VOID(gatherNode); + auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, + ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); + CHECK_NULL_VOID(textNode); + textNode->MountToParent(wrapperNode); + textNode->MarkModifyDone(); +} + +void CustomPreviewNodeProc(const RefPtr& previewNode, const MenuParam& menuParam, + const RefPtr& previewCustomNode = nullptr) +{ + CHECK_NULL_VOID(previewCustomNode); + CHECK_NULL_VOID(previewNode); + auto previewPattern = previewNode->GetPattern(); + CHECK_NULL_VOID(previewPattern); + previewPattern->SetHasPreviewTransitionEffect(menuParam.hasPreviewTransitionEffect); + auto layoutProperty = previewNode->GetLayoutProperty(); + CHECK_NULL_VOID(layoutProperty); + layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true); + previewNode->AddChild(previewCustomNode); + + CHECK_NULL_VOID(menuParam.isShowHoverImage); + previewNode->Measure(layoutProperty->GetLayoutConstraint()); + auto previewSize = previewNode->GetGeometryNode()->GetFrameSize(); + previewPattern->SetIsShowHoverImage(true); + previewPattern->SetCustomPreviewWidth(previewSize.Width()); + previewPattern->SetCustomPreviewHeight(previewSize.Height()); +} + // create menuWrapper and menu node, update menu props std::pair, RefPtr> CreateMenu(int32_t targetId, const std::string& targetTag = "", - MenuType type = MenuType::MENU, const bool hasPreviewTransitionEffect = false, - const RefPtr& previewCustomNode = nullptr) + MenuType type = MenuType::MENU) { // use wrapper to detect click events outside menu auto wrapperNode = FrameNode::CreateFrameNode(V2::MENU_WRAPPER_ETS_TAG, @@ -92,32 +129,6 @@ std::pair, RefPtr> CreateMenu(int32_t targetId, con } menuNode->MountToParent(wrapperNode); - if (previewCustomNode) { - // create previewNode - auto previewNode = FrameNode::CreateFrameNode(V2::MENU_PREVIEW_ETS_TAG, - ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr()); - CHECK_NULL_RETURN(previewNode, std::make_pair(wrapperNode, menuNode)); - auto previewPattern = previewNode->GetPattern(); - previewPattern->SetHasPreviewTransitionEffect(hasPreviewTransitionEffect); - auto layoutProperty = previewNode->GetLayoutProperty(); - layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true); - previewNode->AddChild(previewCustomNode); - previewNode->MountToParent(wrapperNode); - previewNode->MarkModifyDone(); - SetSelfAndChildDraggableFalse(previewCustomNode); - - auto pipeline = PipelineContext::GetMainPipelineContext(); - CHECK_NULL_RETURN(pipeline, std::make_pair(wrapperNode, menuNode)); - auto manager = pipeline->GetOverlayManager(); - CHECK_NULL_RETURN(manager, std::make_pair(wrapperNode, menuNode)); - auto gatherNode = manager->GetGatherNode(); - CHECK_NULL_RETURN(gatherNode, std::make_pair(wrapperNode, menuNode)); - auto textNode = FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, - ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); - CHECK_NULL_RETURN(textNode, std::make_pair(wrapperNode, menuNode)); - textNode->MountToParent(wrapperNode); - textNode->MarkModifyDone(); - } return { wrapperNode, menuNode }; } @@ -269,12 +280,85 @@ void ShowBorderRadiusAndShadowAnimation(const RefPtr& menuTheme, cons option.GetOnFinishEvent()); } -void ShowPixelMapAnimation(const RefPtr& imageNode, const RefPtr& menuNode) +void SetHoverImageFinishEvent(const RefPtr& imageContext, const RefPtr& menuTheme, + bool isShow, bool isScaleNearEqual = true) { - auto menuPattern = GetMenuPattern(menuNode); + CHECK_NULL_VOID(isShow); + CHECK_NULL_VOID(imageContext && menuTheme); + // hover image disappear opacity animation + AnimationOption option; + if (isScaleNearEqual) { + option.SetDuration(menuTheme->GetPreviewAnimationDuration()); + option.SetCurve(Curves::SHARP); + option.SetDelay(menuTheme->GetHoverImageDelayDuration()); + } else { + option.SetDuration(menuTheme->GetHoverImageSwitchToPreviewOpacityDuration()); + option.SetCurve(Curves::FRICTION); + } + imageContext->UpdateOpacity(1.0); + AnimationUtils::Animate( + option, [imageContext]() { + if (imageContext) { + imageContext->UpdateOpacity(0.0); + } + }, + option.GetOnFinishEvent()); +} + +void ShowPixelMapScaleAnimationProc(const RefPtr& menuTheme, const RefPtr& imageContext, + const RefPtr& menuPattern, const MenuParam& menuParam) +{ + auto scaleBefore = menuParam.isShowHoverImage ? menuParam.hoverImageAnimationOptions.scaleFrom : + menuPattern->GetPreviewBeforeAnimationScale(); + auto scaleAfter = menuParam.isShowHoverImage ? menuParam.hoverImageAnimationOptions.scaleTo : + menuPattern->GetPreviewAfterAnimationScale(); + DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LIFT_STARTED); + auto previewBeforeAnimationScale = + LessNotEqual(scaleBefore, 0.0) ? menuTheme->GetPreviewBeforeAnimationScale() : scaleBefore; + auto previewAfterAnimationScale = + LessNotEqual(scaleAfter, 0.0) ? menuTheme->GetPreviewAfterAnimationScale() : scaleAfter; + + imageContext->UpdateTransformScale(VectorF(previewBeforeAnimationScale, previewBeforeAnimationScale)); + + AnimationOption scaleOption = AnimationOption(); + if (menuParam.isShowHoverImage) { + scaleOption.SetDuration(menuTheme->GetHoverImageDelayDuration()); + scaleOption.SetCurve(Curves::SHARP); + } else { + auto motion = AceType::MakeRefPtr( + menuTheme->GetSpringMotionResponse(), menuTheme->GetSpringMotionDampingFraction()); + scaleOption.SetCurve(motion); + } + + // when the scaling start and end sizes are the same, the end callback method should not be relied on + bool isScaleNearEqual = NearEqual(previewBeforeAnimationScale, previewAfterAnimationScale); + if (isScaleNearEqual) { + SetHoverImageFinishEvent(imageContext, menuTheme, menuParam.isShowHoverImage); + scaleOption.SetOnFinishEvent([]() { + DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LIFT_FINISHED); + }); + } else { + scaleOption.SetOnFinishEvent( + [imageContext, menuTheme, isShow = menuParam.isShowHoverImage, isScaleNearEqual]() { + DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LIFT_FINISHED); + SetHoverImageFinishEvent(imageContext, menuTheme, isShow, isScaleNearEqual); + }); + } + AnimationUtils::Animate( + scaleOption, + [imageContext, previewAfterAnimationScale]() { + if (imageContext) { + imageContext->UpdateTransformScale(VectorF(previewAfterAnimationScale, previewAfterAnimationScale)); + } + }, + scaleOption.GetOnFinishEvent()); +} + +void ShowPixelMapAnimation(const RefPtr& imageNode, const RefPtr& wrapperNode, + const RefPtr& previewNode, const MenuParam& menuParam) +{ + auto menuPattern = GetMenuPattern(wrapperNode); CHECK_NULL_VOID(menuPattern); - auto scaleBefore = menuPattern->GetPreviewBeforeAnimationScale(); - auto scaleAfter = menuPattern->GetPreviewAfterAnimationScale(); auto imageContext = imageNode->GetRenderContext(); CHECK_NULL_VOID(imageContext); imageContext->SetClipToBounds(true); @@ -282,34 +366,13 @@ void ShowPixelMapAnimation(const RefPtr& imageNode, const RefPtrGetTheme(); CHECK_NULL_VOID(menuTheme); - auto menuWrapperPattern = menuNode->GetPattern(); + auto menuWrapperPattern = wrapperNode->GetPattern(); CHECK_NULL_VOID(menuWrapperPattern); if (menuWrapperPattern->HasPreviewTransitionEffect()) { auto layoutProperty = imageNode->GetLayoutProperty(); layoutProperty->UpdateVisibility(VisibleType::VISIBLE, true); } else { - DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LIFT_STARTED); - auto previewBeforeAnimationScale = - LessNotEqual(scaleBefore, 0.0) ? menuTheme->GetPreviewBeforeAnimationScale() : scaleBefore; - auto previewAfterAnimationScale = - LessNotEqual(scaleAfter, 0.0) ? menuTheme->GetPreviewAfterAnimationScale() : scaleAfter; - - imageContext->UpdateTransformScale(VectorF(previewBeforeAnimationScale, previewBeforeAnimationScale)); - - AnimationOption scaleOption = AnimationOption(); - auto motion = AceType::MakeRefPtr( - menuTheme->GetSpringMotionResponse(), menuTheme->GetSpringMotionDampingFraction()); - scaleOption.SetCurve(motion); - scaleOption.SetOnFinishEvent( - []() { DragEventActuator::ExecutePreDragAction(PreDragStatus::PREVIEW_LIFT_FINISHED); }); - AnimationUtils::Animate( - scaleOption, - [imageContext, previewAfterAnimationScale]() { - if (imageContext) { - imageContext->UpdateTransformScale(VectorF(previewAfterAnimationScale, previewAfterAnimationScale)); - } - }, - scaleOption.GetOnFinishEvent()); + ShowPixelMapScaleAnimationProc(menuTheme, imageContext, menuPattern, menuParam); } ShowBorderRadiusAndShadowAnimation(menuTheme, imageContext); @@ -367,7 +430,50 @@ void InitPanEvent(const RefPtr& gestureHub, const RefPtrAddPanEvent(panEvent, panDirection, 1, DEFAULT_PAN_DISTANCE); } -void SetPixelMap(const RefPtr& target, const RefPtr& menuNode) +float GetHoverImageCustomPreviewBaseScaleInfo(const MenuParam& menuParam, int32_t width, int32_t height, + float previewWidth, float previewHeight) +{ + float scaleRet = 1.0f; + CHECK_NULL_RETURN(menuParam.isShowHoverImage, scaleRet); + if (previewWidth - width < previewHeight - height) { + CHECK_EQUAL_RETURN(previewWidth, 0, scaleRet); + scaleRet = width / previewWidth; + } else { + CHECK_EQUAL_RETURN(previewHeight, 0, scaleRet); + scaleRet = height / previewHeight; + } + return scaleRet; +} + +void SetHoverImageCustomPreviewInfo(const RefPtr& previewNode, const MenuParam& menuParam, + int32_t width, int32_t height) +{ + CHECK_NULL_VOID(previewNode); + auto previewPattern = previewNode->GetPattern(); + CHECK_NULL_VOID(previewPattern); + auto previewWidth = previewPattern->GetCustomPreviewWidth(); + auto previewHeight = previewPattern->GetCustomPreviewHeight(); + auto scale = GetHoverImageCustomPreviewBaseScaleInfo(menuParam, width, height, previewWidth, previewHeight); + CHECK_NULL_VOID(scale); + auto hoverImageScaleTo = menuParam.hoverImageAnimationOptions.scaleTo; + hoverImageScaleTo = LessOrEqual(hoverImageScaleTo, 0.0) ? hoverImageScaleTo : 1.0f; + auto previewScaleFrom = LessOrEqual(menuParam.previewAnimationOptions.scaleFrom, 0.0) ? scale * hoverImageScaleTo : + menuParam.previewAnimationOptions.scaleFrom; + previewPattern->SetCustomPreviewScaleFrom(previewScaleFrom); + + auto previewScaleTo = menuParam.previewAnimationOptions.scaleTo; + CHECK_NULL_VOID(previewScaleTo); + previewPattern->SetCustomPreviewScaleTo(previewScaleTo); + previewPattern->SetHoverImageDisAppearScaleTo(previewScaleTo / scale); + + auto previewPositionXDist = (previewWidth - width) / HALF_DIVIDER_VALUE; + auto previewPositionYDist = (previewHeight - height) / HALF_DIVIDER_VALUE; + previewPattern->SetCustomPreviewPositionXDist(previewPositionXDist); + previewPattern->SetCustomPreviewPositionYDist(previewPositionYDist); +} + +void SetPixelMap(const RefPtr& target, const RefPtr& wrapperNode, + const RefPtr& previewNode, const MenuParam& menuParam) { CHECK_NULL_VOID(target); auto eventHub = target->GetEventHub(); @@ -378,6 +484,8 @@ void SetPixelMap(const RefPtr& target, const RefPtr& menuN CHECK_NULL_VOID(pixelMap); auto width = pixelMap->GetWidth(); auto height = pixelMap->GetHeight(); + SetHoverImageCustomPreviewInfo(previewNode, menuParam, width, height); + auto imageOffset = GetFloatImageOffset(target); auto imageNode = FrameNode::GetOrCreateFrameNode(V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); @@ -393,17 +501,19 @@ void SetPixelMap(const RefPtr& target, const RefPtr& menuN CHECK_NULL_VOID(hub); auto imageGestureHub = hub->GetOrCreateGestureEventHub(); CHECK_NULL_VOID(imageGestureHub); - InitPanEvent(imageGestureHub, menuNode); + InitPanEvent(imageGestureHub, wrapperNode); - ShowGatherAnimation(target, menuNode); + if (!menuParam.isShowHoverImage) { + ShowGatherAnimation(target, wrapperNode); + } auto imageContext = imageNode->GetRenderContext(); CHECK_NULL_VOID(imageContext); imageContext->UpdatePosition(OffsetT(Dimension(imageOffset.GetX()), Dimension(imageOffset.GetY()))); imageNode->MarkModifyDone(); - imageNode->MountToParent(menuNode); - auto menuWrapperPattern = menuNode->GetPattern(); + imageNode->MountToParent(wrapperNode); + auto menuWrapperPattern = wrapperNode->GetPattern(); CHECK_NULL_VOID(menuWrapperPattern); - ShowPixelMapAnimation(imageNode, menuNode); + ShowPixelMapAnimation(imageNode, wrapperNode, previewNode, menuParam); } void SetFilter(const RefPtr& targetNode, const RefPtr& menuWrapperNode) @@ -551,22 +661,50 @@ void SetPreviewTransitionEffect(const RefPtr &menuWrapperNode, const pattern->SetHasPreviewTransitionEffect(menuParam.hasPreviewTransitionEffect); } +void SetPreviewScaleAndHoverImageScale(const RefPtr& menuNode, const MenuParam& menuParam) +{ + auto pattern = menuNode->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->SetPreviewMode(menuParam.previewMode); + pattern->SetPreviewBeforeAnimationScale(menuParam.previewAnimationOptions.scaleFrom); + pattern->SetPreviewAfterAnimationScale(menuParam.previewAnimationOptions.scaleTo); + pattern->SetIsShowHoverImage(menuParam.isShowHoverImage); + pattern->SetHoverImageBeforeAnimationScale(menuParam.hoverImageAnimationOptions.scaleFrom); + pattern->SetHoverImageAfterAnimationScale(menuParam.hoverImageAnimationOptions.scaleTo); +} + +void SetCustomPreviewOpacityWhenHoverImage(const RefPtr& menuWrapperNode, const MenuParam& menuParam) +{ + CHECK_NULL_VOID(menuParam.isShowHoverImage); + CHECK_NULL_VOID(menuWrapperNode); + auto menuWrapperPattern = menuWrapperNode->GetPattern(); + CHECK_NULL_VOID(menuWrapperPattern); + menuWrapperPattern->SetIsShowHoverImage(menuParam.isShowHoverImage); + auto preview = menuWrapperPattern->GetPreview(); + CHECK_NULL_VOID(preview); + auto previewRenderContext = preview->GetRenderContext(); + CHECK_NULL_VOID(previewRenderContext); + previewRenderContext->UpdateOpacity(0.0); +} + // create menu with custom node from a builder RefPtr MenuView::Create(const RefPtr& customNode, int32_t targetId, const std::string& targetTag, const MenuParam& menuParam, bool withWrapper, const RefPtr& previewCustomNode) { auto type = menuParam.type; - auto [wrapperNode, menuNode] = CreateMenu(targetId, targetTag, type, menuParam.hasPreviewTransitionEffect, - previewCustomNode); + auto [wrapperNode, menuNode] = CreateMenu(targetId, targetTag, type); + // create previewNode + auto previewNode = FrameNode::CreateFrameNode(V2::MENU_PREVIEW_ETS_TAG, + ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr()); + CHECK_NULL_RETURN(previewNode, nullptr); + CustomPreviewNodeProc(previewNode, menuParam, previewCustomNode); + MountTextNode(wrapperNode, previewCustomNode); + UpdateMenuBackgroundStyle(menuNode, menuParam); SetPreviewTransitionEffect(wrapperNode, menuParam); SetHasCustomRadius(wrapperNode, menuNode, menuParam); - auto pattern = menuNode->GetPattern(); - if (pattern) { - pattern->SetPreviewMode(menuParam.previewMode); - pattern->SetPreviewBeforeAnimationScale(menuParam.previewAnimationOptions.scaleFrom); - pattern->SetPreviewAfterAnimationScale(menuParam.previewAnimationOptions.scaleTo); - } + + SetPreviewScaleAndHoverImageScale(menuNode, menuParam); // put custom node in a scroll to limit its height auto scroll = CreateMenuScroll(customNode); CHECK_NULL_RETURN(scroll, nullptr); @@ -595,8 +733,14 @@ RefPtr MenuView::Create(const RefPtr& customNode, int32_t tar if (type == MenuType::CONTEXT_MENU && menuParam.previewMode != MenuPreviewMode::NONE) { auto targetNode = FrameNode::GetFrameNode(targetTag, targetId); SetFilter(targetNode, wrapperNode); - if (menuParam.previewMode == MenuPreviewMode::IMAGE) { - SetPixelMap(targetNode, wrapperNode); + if (menuParam.previewMode == MenuPreviewMode::IMAGE || menuParam.isShowHoverImage) { + SetPixelMap(targetNode, wrapperNode, previewNode, menuParam); + } + if (menuParam.previewMode == MenuPreviewMode::CUSTOM) { + previewNode->MountToParent(wrapperNode); + previewNode->MarkModifyDone(); + SetSelfAndChildDraggableFalse(previewCustomNode); + SetCustomPreviewOpacityWhenHoverImage(wrapperNode, menuParam); } } return 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 237d77a2df3..23cec21a428 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 @@ -26,6 +26,10 @@ namespace OHOS::Ace::NG { namespace { constexpr float PAN_MAX_VELOCITY = 2000.0f; +// custom preview animation params when hover image +const RefPtr CUSTOM_PREVIEW_ANIMATION_CURVE = + AceType::MakeRefPtr(0.0f, 1.0f, 280.0f, 30.0f); + RefPtr GetMenuPattern(const RefPtr& menuWrapper) { CHECK_NULL_RETURN(menuWrapper, nullptr); @@ -36,9 +40,52 @@ RefPtr GetMenuPattern(const RefPtr& menuWrapper) return menuNode->GetPattern(); } -void ShowScaleAnimation( - const RefPtr& context, const RefPtr& menuTheme, const RefPtr& menuPattern) +bool ShowPreviewAnimationAfterHoverImage(const RefPtr& context, const RefPtr& menuTheme, + const RefPtr& menuPattern, float scaleFrom, float scaleTo) { + CHECK_NULL_RETURN(menuPattern, false); + if (!menuPattern->GetIsShowHoverImage()) { + return false; + } + CHECK_NULL_RETURN(context, false); + CHECK_NULL_RETURN(menuTheme, false); + context->UpdateOpacity(0.0); + // custom preview update opacity + AnimationOption option; + option.SetDuration(menuTheme->GetHoverImageSwitchToPreviewOpacityDuration()); + option.SetDelay(menuTheme->GetHoverImageDelayDuration()); + option.SetCurve(Curves::FRICTION); + AnimationUtils::Animate( + option, [context]() { + CHECK_NULL_VOID(context); + context->UpdateOpacity(1.0); + }, + option.GetOnFinishEvent()); + + // custom preview update scale from hover image size to final scale + auto scaleBefore = LessNotEqual(scaleFrom, 0.0) ? menuTheme->GetPreviewBeforeAnimationScale() : scaleFrom; + auto scaleAfter = LessNotEqual(scaleTo, 0.0) ? menuTheme->GetPreviewAfterAnimationScale() : scaleTo; + context->UpdateTransformScale(VectorF(scaleBefore, scaleBefore)); + + AnimationOption scaleOption = AnimationOption(); + scaleOption.SetCurve(CUSTOM_PREVIEW_ANIMATION_CURVE); + scaleOption.SetDelay(menuTheme->GetHoverImageDelayDuration()); + AnimationUtils::Animate( + scaleOption, + [context, scaleAfter]() { + CHECK_NULL_VOID(context); + context->UpdateTransformScale(VectorF(scaleAfter, scaleAfter)); + }, + scaleOption.GetOnFinishEvent()); + return true; +} + +void ShowScaleAnimation(const RefPtr& context, const RefPtr& menuTheme, + const RefPtr& menuPattern, float scaleFrom, float scaleTo) +{ + if (ShowPreviewAnimationAfterHoverImage(context, menuTheme, menuPattern, scaleFrom, scaleTo)) { + return; + } CHECK_NULL_VOID(context); CHECK_NULL_VOID(menuTheme); auto scaleBefore { -1.0f }; @@ -64,9 +111,8 @@ void ShowScaleAnimation( AnimationUtils::Animate( scaleOption, [context, previewAfterAnimationScale]() { - if (context) { - context->UpdateTransformScale(VectorF(previewAfterAnimationScale, previewAfterAnimationScale)); - } + CHECK_NULL_VOID(context); + context->UpdateTransformScale(VectorF(previewAfterAnimationScale, previewAfterAnimationScale)); }, scaleOption.GetOnFinishEvent()); } @@ -108,9 +154,7 @@ void MenuPreviewPattern::OnModifyDone() bool MenuPreviewPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, const DirtySwapConfig& config) { - if (!isFirstShow_) { - return false; - } + CHECK_NULL_RETURN(isFirstShow_, false); auto host = GetHost(); CHECK_NULL_RETURN(host, false); auto context = host->GetRenderContext(); @@ -128,28 +172,33 @@ bool MenuPreviewPattern::OnDirtyLayoutWrapperSwap(const RefPtr& d auto previewAnimationDuration = menuTheme->GetPreviewAnimationDuration(); auto previewBorderRadius = menuTheme->GetPreviewBorderRadius(); + auto delay = isShowHoverImage_ ? menuTheme->GetHoverImageDelayDuration() : 0; AnimationOption option; option.SetDuration(previewAnimationDuration); - option.SetCurve(Curves::SHARP); + if (isShowHoverImage_) { + option.SetCurve(CUSTOM_PREVIEW_ANIMATION_CURVE); + } else { + option.SetCurve(Curves::SHARP); + } + option.SetDelay(delay); AnimationUtils::Animate( option, [context, previewBorderRadius, shadow]() mutable { - if (context) { - auto color = shadow->GetColor(); - auto newColor = Color::FromARGB(100, color.GetRed(), color.GetGreen(), color.GetBlue()); - shadow->SetColor(newColor); - context->UpdateBackShadow(shadow.value()); - BorderRadiusProperty borderRadius; - borderRadius.SetRadius(previewBorderRadius); - context->UpdateBorderRadius(borderRadius); - } + CHECK_NULL_VOID(context); + auto color = shadow->GetColor(); + auto newColor = Color::FromARGB(100, color.GetRed(), color.GetGreen(), color.GetBlue()); + shadow->SetColor(newColor); + context->UpdateBackShadow(shadow.value()); + BorderRadiusProperty borderRadius; + borderRadius.SetRadius(previewBorderRadius); + context->UpdateBorderRadius(borderRadius); }, option.GetOnFinishEvent()); if (!hasPreviewTransitionEffect_) { auto menuWrapper = GetMenuWrapper(); auto menuPattern = GetMenuPattern(menuWrapper); ShowGatherAnimation(host, menuWrapper); - ShowScaleAnimation(context, menuTheme, menuPattern); + ShowScaleAnimation(context, menuTheme, menuPattern, customPreviewScaleFrom_, customPreviewScaleTo_); } isFirstShow_ = false; return false; @@ -201,4 +250,38 @@ void MenuPreviewPattern::HandleDragEnd(float offsetX, float offsetY, float veloc CHECK_NULL_VOID(wrapperPattern); wrapperPattern->HideMenu(); } + +void MenuPreviewPattern::ShowHoverImagePreviewDisAppearAnimation(const RefPtr& context, + float scaleFrom, float scaleTo, int32_t duration) +{ + CHECK_NULL_VOID(isShowHoverImage_); + CHECK_NULL_VOID(context); + + // custom preview update disappear opacity + context->UpdateOpacity(1.0); + AnimationOption option; + option.SetDuration(duration); + option.SetCurve(Curves::FRICTION); + AnimationUtils::Animate( + option, [context]() { + CHECK_NULL_VOID(context); + context->UpdateOpacity(0.0); + }, + option.GetOnFinishEvent()); + + // custom preview update scale from final scale to hover image size + auto scaleBefore = LessNotEqual(scaleFrom, 0.0) ? 1.0f : scaleFrom; + auto scaleAfter = LessNotEqual(scaleTo, 0.0) ? 1.0f : scaleTo; + context->UpdateTransformScale(VectorF(scaleBefore, scaleBefore)); + + AnimationOption scaleOption = AnimationOption(); + scaleOption.SetCurve(CUSTOM_PREVIEW_ANIMATION_CURVE); + AnimationUtils::Animate( + scaleOption, + [context, scaleAfter]() { + CHECK_NULL_VOID(context); + context->UpdateTransformScale(VectorF(scaleAfter, scaleAfter)); + }, + scaleOption.GetOnFinishEvent()); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/menu/preview/menu_preview_pattern.h b/frameworks/core/components_ng/pattern/menu/preview/menu_preview_pattern.h index b6f6dd839ec..698f6263816 100644 --- a/frameworks/core/components_ng/pattern/menu/preview/menu_preview_pattern.h +++ b/frameworks/core/components_ng/pattern/menu/preview/menu_preview_pattern.h @@ -50,6 +50,89 @@ public: hasPreviewTransitionEffect_ = hasPreviewTransitionEffect; } + void SetIsShowHoverImage(bool isShow) + { + isShowHoverImage_ = isShow; + } + + bool GetIsShowHoverImage() const + { + return isShowHoverImage_; + } + + void SetCustomPreviewWidth(float width) + { + customPreviewWidth_ = width; + } + + float GetCustomPreviewWidth() const + { + return customPreviewWidth_; + } + + void SetCustomPreviewHeight(float height) + { + customPreviewHeight_ = height; + } + + float GetCustomPreviewHeight() const + { + return customPreviewHeight_; + } + + void SetCustomPreviewScaleFrom(float scaleFrom) + { + customPreviewScaleFrom_ = scaleFrom; + } + + float GetCustomPreviewScaleFrom() const + { + return customPreviewScaleFrom_; + } + + void SetCustomPreviewScaleTo(float scaleTo) + { + customPreviewScaleTo_ = scaleTo; + } + + float GetCustomPreviewScaleTo() const + { + return customPreviewScaleTo_; + } + + void SetHoverImageDisAppearScaleTo(float scaleTo) + { + hoverImageDisAppearScale_ = scaleTo; + } + + float GetHoverImageDisAppearScaleTo() const + { + return hoverImageDisAppearScale_; + } + + void SetCustomPreviewPositionXDist(float xDist) + { + previewPositionXDist_ = xDist; + } + + float GetCustomPreviewPositionXDist() + { + return previewPositionXDist_; + } + + void SetCustomPreviewPositionYDist(float yDist) + { + previewPositionYDist_ = yDist; + } + + float GetCustomPreviewPositionYDist() + { + return previewPositionYDist_; + } + + void ShowHoverImagePreviewDisAppearAnimation(const RefPtr& context, float scaleFrom, float scaleTo, + int32_t duration = 0); + RefPtr GetMenuWrapper() const; private: @@ -59,6 +142,15 @@ private: void HandleDragEnd(float offsetX, float offsetY, float velocity); bool isFirstShow_ = false; bool hasPreviewTransitionEffect_ = false; + + bool isShowHoverImage_ = false; + float customPreviewWidth_ = 0.0f; + float customPreviewHeight_ = 0.0f; + float customPreviewScaleFrom_ = 1.0f; + float customPreviewScaleTo_ = 1.0f; + float hoverImageDisAppearScale_ = 1.0f; + float previewPositionXDist_ = 0.0f; + float previewPositionYDist_ = 0.0f; ACE_DISALLOW_COPY_AND_MOVE(MenuPreviewPattern); }; } // namespace OHOS::Ace::NG 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 ddf85cdddb8..b2c0738b0e9 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 @@ -126,6 +126,23 @@ public: CHECK_NULL_RETURN(host, nullptr); auto preview = AceType::DynamicCast(host->GetChildAtIndex(1)); CHECK_NULL_RETURN(preview, nullptr); + auto hoverImageCustomPreview = AceType::DynamicCast(host->GetChildAtIndex(2)); + CHECK_NULL_RETURN(hoverImageCustomPreview, preview); + if (hoverImageCustomPreview->GetTag() == V2::MENU_PREVIEW_ETS_TAG) { + return hoverImageCustomPreview; + } + return preview; + } + + RefPtr GetHoverImagePreview() const + { + auto host = GetHost(); + CHECK_NULL_RETURN(host, nullptr); + auto preview = AceType::DynamicCast(host->GetChildAtIndex(1)); + CHECK_NULL_RETURN(preview, nullptr); + if (preview->GetTag() != V2::IMAGE_ETS_TAG) { + return nullptr; + } return preview; } @@ -136,6 +153,10 @@ public: CHECK_NULL_RETURN(host, nullptr); auto badgeNode = AceType::DynamicCast(host->GetChildAtIndex(2)); CHECK_NULL_RETURN(badgeNode, nullptr); + if (badgeNode->GetTag() == V2::MENU_PREVIEW_ETS_TAG) { + auto badgeNode = AceType::DynamicCast(host->GetChildAtIndex(3)); + CHECK_NULL_RETURN(badgeNode, nullptr); + } if (badgeNode->GetTag() != V2::TEXT_ETS_TAG) { return nullptr; } @@ -155,6 +176,16 @@ public: isFirstShow_ = true; } + void SetIsShowHoverImage(bool isShow) + { + isShowHoverImage_ = isShow; + } + + bool GetIsShowHoverImage() + { + return isShowHoverImage_; + } + void RegisterMenuCallback(const RefPtr& menuWrapperNode, const MenuParam& menuParam); void RegisterMenuAppearCallback(const std::function& onAppear) @@ -359,6 +390,7 @@ private: Placement menuPlacement_ = Placement::NONE; bool isFirstShow_ = true; bool isShowInSubWindow_ = true; + bool isShowHoverImage_ = false; MenuStatus menuStatus_ = MenuStatus::INIT; bool hasTransitionEffect_ = false; bool hasPreviewTransitionEffect_ = false; diff --git a/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp b/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp index 7a03593eabd..0c0e4f56aa1 100644 --- a/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp +++ b/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp @@ -138,10 +138,72 @@ RefPtr GetLastPage() return pageNode; } -void ShowPreviewDisappearAnimation(const RefPtr& menuWrapperPattern) +void ShowPreviewBgDisappearAnimationProc(const RefPtr& previewRenderContext, + const RefPtr& menuTheme) +{ + auto shadow = previewRenderContext->GetBackShadow(); + if (!shadow.has_value()) { + shadow = Shadow::CreateShadow(ShadowStyle::None); + } + previewRenderContext->UpdateBackShadow(shadow.value()); + auto disappearDuration = menuTheme->GetDisappearDuration(); + AnimationOption previewOption; + previewOption.SetCurve(Curves::SHARP); + previewOption.SetDuration(disappearDuration); + AnimationUtils::Animate(previewOption, [previewRenderContext, shadow]() mutable { + CHECK_NULL_VOID(previewRenderContext); + auto color = shadow->GetColor(); + auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue()); + shadow->SetColor(newColor); + previewRenderContext->UpdateBackShadow(shadow.value()); + BorderRadiusProperty borderRadius; + borderRadius.SetRadius(0.0_vp); + previewRenderContext->UpdateBorderRadius(borderRadius); + }); +} + +bool ShowHoverImagePreviewDisappearAnimation(const RefPtr& menuTheme, + const RefPtr& menuPattern, RefPtr& previewChild) +{ + CHECK_NULL_RETURN(menuPattern, false); + CHECK_NULL_RETURN(menuPattern->GetIsShowHoverImage(), false); + + CHECK_NULL_RETURN(previewChild, false); + auto previewRenderContext = previewChild->GetRenderContext(); + CHECK_NULL_RETURN(previewRenderContext, false); + + auto duration = menuTheme->GetHoverImageDisAppearDuration(); + if (previewChild->GetTag() == V2::MENU_PREVIEW_ETS_TAG) { + auto previewPattern = previewChild->GetPattern(); + CHECK_NULL_RETURN(previewPattern, false); + // reverse scale + auto disappearScaleFrom = previewPattern->GetCustomPreviewScaleTo(); + auto disappearScaleTo = previewPattern->GetCustomPreviewScaleFrom(); + duration = menuTheme->GetHoverImagePreviewDisAppearDuration(); + previewPattern->ShowHoverImagePreviewDisAppearAnimation(previewRenderContext, + disappearScaleFrom, disappearScaleTo, duration); + // not proc next + return false; + } + + // hover image update opacity + previewRenderContext->UpdateOpacity(0.0); + AnimationOption option; + option.SetDuration(duration); + option.SetCurve(Curves::FRICTION); + AnimationUtils::Animate( + option, [previewRenderContext]() { + CHECK_NULL_VOID(previewRenderContext); + previewRenderContext->UpdateOpacity(1.0); + }, + option.GetOnFinishEvent()); + return true; +} + +void ShowPreviewDisappearAnimationProc(const RefPtr& menuWrapperPattern, + RefPtr& previewChild, float xDist = 0.0f, float yDist = 0.0f) { CHECK_NULL_VOID(menuWrapperPattern); - auto previewChild = menuWrapperPattern->GetPreview(); CHECK_NULL_VOID(previewChild); auto previewRenderContext = previewChild->GetRenderContext(); CHECK_NULL_VOID(previewRenderContext); @@ -161,13 +223,16 @@ void ShowPreviewDisappearAnimation(const RefPtr& menuWrapper CHECK_NULL_VOID(pipelineContext); auto menuTheme = pipelineContext->GetTheme(); CHECK_NULL_VOID(menuTheme); + CHECK_NULL_VOID(ShowHoverImagePreviewDisappearAnimation(menuTheme, menuPattern, previewChild)); + auto springMotionResponse = menuTheme->GetPreviewDisappearSpringMotionResponse(); auto springMotionDampingFraction = menuTheme->GetPreviewDisappearSpringMotionDampingFraction(); AnimationOption scaleOption; auto motion = AceType::MakeRefPtr(springMotionResponse, springMotionDampingFraction); scaleOption.SetCurve(motion); float previewScale = 1.0f; - if (menuPattern->GetPreviewMode() == MenuPreviewMode::IMAGE) { + if (menuPattern->GetPreviewMode() == MenuPreviewMode::IMAGE || + (menuPattern->GetIsShowHoverImage() && previewChild->GetTag() == V2::IMAGE_ETS_TAG)) { auto previewGeometryNode = previewChild->GetGeometryNode(); CHECK_NULL_VOID(previewGeometryNode); auto preivewSize = previewGeometryNode->GetFrameSize(); @@ -175,34 +240,33 @@ void ShowPreviewDisappearAnimation(const RefPtr& menuWrapper previewScale = menuPattern->GetTargetSize().Width() / preivewSize.Width(); } } - AnimationUtils::Animate(scaleOption, [previewRenderContext, previewPosition, previewScale]() { - if (previewRenderContext) { - previewRenderContext->UpdateTransformScale(VectorF(previewScale, previewScale)); - previewRenderContext->UpdatePosition( - OffsetT(Dimension(previewPosition.GetX()), Dimension(previewPosition.GetY()))); - } - }); - auto shadow = previewRenderContext->GetBackShadow(); - if (!shadow.has_value()) { - shadow = Shadow::CreateShadow(ShadowStyle::None); - } - previewRenderContext->UpdateBackShadow(shadow.value()); - auto disappearDuration = menuTheme->GetDisappearDuration(); - AnimationOption previewOption; - previewOption.SetCurve(Curves::SHARP); - previewOption.SetDuration(disappearDuration); - AnimationUtils::Animate(previewOption, [previewRenderContext, shadow]() mutable { - if (previewRenderContext) { - auto color = shadow->GetColor(); - auto newColor = Color::FromARGB(1, color.GetRed(), color.GetGreen(), color.GetBlue()); - shadow->SetColor(newColor); - previewRenderContext->UpdateBackShadow(shadow.value()); - BorderRadiusProperty borderRadius; - borderRadius.SetRadius(0.0_vp); - previewRenderContext->UpdateBorderRadius(borderRadius); - } + auto xPosition = previewPosition.GetX() + xDist; + auto yPosition = previewPosition.GetY() + yDist; + AnimationUtils::Animate(scaleOption, [previewRenderContext, xPosition, yPosition, previewScale]() { + CHECK_NULL_VOID(previewRenderContext); + previewRenderContext->UpdateTransformScale(VectorF(previewScale, previewScale)); + previewRenderContext->UpdatePosition( + OffsetT(Dimension(xPosition), Dimension(yPosition))); }); + ShowPreviewBgDisappearAnimationProc(previewRenderContext, menuTheme); +} + +void ShowPreviewDisappearAnimation(const RefPtr& menuWrapperPattern) +{ + CHECK_NULL_VOID(menuWrapperPattern); + auto previewChild = menuWrapperPattern->GetPreview(); + CHECK_NULL_VOID(previewChild); + ShowPreviewDisappearAnimationProc(menuWrapperPattern, previewChild); + + CHECK_NULL_VOID(menuWrapperPattern->GetIsShowHoverImage()); + auto hoverImagePreview = menuWrapperPattern->GetHoverImagePreview(); + CHECK_NULL_VOID(hoverImagePreview); + auto previewPattern = previewChild->GetPattern(); + CHECK_NULL_VOID(previewPattern); + auto xDist = previewPattern->GetCustomPreviewPositionXDist(); + auto yDist = previewPattern->GetCustomPreviewPositionYDist(); + ShowPreviewDisappearAnimationProc(menuWrapperPattern, hoverImagePreview, xDist, yDist); } void UpdateContextMenuDisappearPositionAnimation(const RefPtr& menu, const NG::OffsetF& offset) @@ -231,10 +295,9 @@ void UpdateContextMenuDisappearPositionAnimation(const RefPtr& menu, auto motion = AceType::MakeRefPtr(springMotionResponse, springMotionDampingFraction); positionOption.SetCurve(motion); AnimationUtils::Animate(positionOption, [menuRenderContext, menuPosition]() { - if (menuRenderContext) { - menuRenderContext->UpdatePosition( - OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); - } + CHECK_NULL_VOID(menuRenderContext); + menuRenderContext->UpdatePosition( + OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); }); } @@ -264,10 +327,9 @@ void ShowContextMenuDisappearAnimation( auto motion = AceType::MakeRefPtr(springMotionResponse, springMotionDampingFraction); positionOption.SetCurve(motion); AnimationUtils::Animate(positionOption, [menuRenderContext, menuPosition]() { - if (menuRenderContext) { - menuRenderContext->UpdatePosition( - OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); - } + CHECK_NULL_VOID(menuRenderContext); + menuRenderContext->UpdatePosition( + OffsetT(Dimension(menuPosition.GetX()), Dimension(menuPosition.GetY()))); }); auto disappearDuration = menuTheme->GetDisappearDuration(); @@ -276,9 +338,8 @@ void ShowContextMenuDisappearAnimation( scaleOption.SetCurve(Curves::FAST_OUT_LINEAR_IN); scaleOption.SetDuration(disappearDuration); AnimationUtils::Animate(scaleOption, [menuRenderContext, menuAnimationScale]() { - if (menuRenderContext) { - menuRenderContext->UpdateTransformScale({ menuAnimationScale, menuAnimationScale }); - } + CHECK_NULL_VOID(menuRenderContext); + menuRenderContext->UpdateTransformScale({ menuAnimationScale, menuAnimationScale }); }); option.SetDuration(disappearDuration); @@ -286,9 +347,8 @@ void ShowContextMenuDisappearAnimation( AnimationUtils::Animate( option, [menuRenderContext]() { - if (menuRenderContext) { - menuRenderContext->UpdateOpacity(0.0); - } + CHECK_NULL_VOID(menuRenderContext); + menuRenderContext->UpdateOpacity(0.0); }, option.GetOnFinishEvent()); } diff --git a/frameworks/core/components_ng/property/menu_property.h b/frameworks/core/components_ng/property/menu_property.h index b102d630f4e..706de0c7147 100644 --- a/frameworks/core/components_ng/property/menu_property.h +++ b/frameworks/core/components_ng/property/menu_property.h @@ -69,6 +69,8 @@ struct MenuParam { MenuType type = MenuType::MENU; MenuPreviewMode previewMode = MenuPreviewMode::NONE; MenuPreviewAnimationOptions previewAnimationOptions; + bool isShowHoverImage = false; + MenuPreviewAnimationOptions hoverImageAnimationOptions; std::optional backgroundEffectOption; std::optional backgroundColor; std::optional backgroundBlurStyle; -- Gitee