From 5912735e9d2ab4a178c5f01d13311becfcfb0da3 Mon Sep 17 00:00:00 2001 From: zhanghang Date: Mon, 25 Aug 2025 20:20:56 +0800 Subject: [PATCH] feat:timePicker Signed-off-by: zhanghang --- .../time_picker/timepicker_column_pattern.cpp | 77 +++++++++++ .../time_picker/timepicker_column_pattern.h | 19 ++- .../time_picker/timepicker_row_pattern.cpp | 123 +++++++++++++++++- .../time_picker/timepicker_row_pattern.h | 17 ++- 4 files changed, 230 insertions(+), 6 deletions(-) diff --git a/frameworks/core/components_ng/pattern/time_picker/timepicker_column_pattern.cpp b/frameworks/core/components_ng/pattern/time_picker/timepicker_column_pattern.cpp index 8ebff0e570b..58f9caa4d4e 100644 --- a/frameworks/core/components_ng/pattern/time_picker/timepicker_column_pattern.cpp +++ b/frameworks/core/components_ng/pattern/time_picker/timepicker_column_pattern.cpp @@ -63,6 +63,8 @@ void TimePickerColumnPattern::OnModifyDone() CHECK_NULL_VOID(theme); pressColor_ = theme->GetPressColor(); hoverColor_ = theme->GetHoverColor(); + useButtonFocusArea_ = theme->NeedButtonFocusAreaType(); + InitSelectorButtonProperties(theme); auto showCount = GetShowCount(); InitOnKeyEvent(focusHub); InitMouseAndPressEvent(); @@ -674,4 +676,79 @@ std::string TimePickerColumnPattern::GetCurrentOption() const } return ""; } + +void TimePickerColumnPattern::InitSelectorButtonProperties(const RefPtr& pickerTheme) +{ + CHECK_NULL_VOID(pickerTheme); + if (useButtonFocusArea_) { + buttonDefaultBgColor_ = pickerTheme->GetSelectorItemNormalBgColor(); + buttonFocusBgColor_ = pickerTheme->GetSelectorItemFocusBgColor(); + buttonDefaultBorderColor_ = pickerTheme->GetSelectorItemBorderColor(); + buttonFocusBorderColor_ = pickerTheme->GetSelectorItemFocusBorderColor(); + selectorTextFocusColor_ = pickerTheme->GetOptionStyle(true, true).GetTextColor(); + pressColor_ = buttonDefaultBgColor_.BlendColor(pickerTheme->GetPressColor()); + hoverColor_ = buttonDefaultBgColor_.BlendColor(pickerTheme->GetHoverColor()); + buttonFocusBorderWidth_ = pickerTheme->GetSelectorItemFocusBorderWidth(); + buttonDefaultBorderWidth_ = pickerTheme->GetSelectorItemBorderWidth(); + } +} + +const Color& TimePickerColumnPattern::GetButtonHoverColor() const +{ + return useButtonFocusArea_ && isFocusColumn_ ? buttonFocusBgColor_ : hoverColor_; +} + +void TimePickerColumnPattern::UpdateColumnButtonFocusState(bool haveFocus, bool needMarkDirty) +{ + auto isInitUpdate = isFirstTimeUpdateButtonProps_ && !haveFocus; + auto isFocusChanged = isFocusColumn_ != haveFocus; + + if (isFocusChanged || isInitUpdate) { + isFocusColumn_ = haveFocus; + UpdateSelectorButtonProps(isFocusColumn_, needMarkDirty); + } + if (isFocusChanged) { + FlushCurrentOptions(); + } + if (isInitUpdate) { + isFirstTimeUpdateButtonProps_ = false; + } +} + +void TimePickerColumnPattern::UpdateSelectorButtonProps(bool haveFocus, bool needMarkDirty) +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto blend = host->GetParent(); + CHECK_NULL_VOID(blend); + auto stack = blend->GetParent(); + CHECK_NULL_VOID(stack); + auto buttonNode = DynamicCast(stack->GetFirstChild()); + CHECK_NULL_VOID(buttonNode); + auto buttonLayoutProperty = buttonNode->GetLayoutProperty(); + CHECK_NULL_VOID(buttonLayoutProperty); + auto renderContext = buttonNode->GetRenderContext(); + CHECK_NULL_VOID(renderContext); + + BorderWidthProperty borderWidth; + BorderColorProperty borderColor; + + if (haveFocus) { + buttonBgColor_ = buttonFocusBgColor_; + borderWidth.SetBorderWidth(buttonFocusBorderWidth_); + borderColor.SetColor(buttonFocusBorderColor_); + } else { + buttonBgColor_ = buttonDefaultBgColor_; + borderWidth.SetBorderWidth(buttonDefaultBorderWidth_); + borderColor.SetColor(buttonDefaultBorderColor_); + } + buttonLayoutProperty->UpdateBorderWidth(borderWidth); + renderContext->UpdateBorderColor(borderColor); + renderContext->UpdateBackgroundColor(buttonBgColor_); + + if (needMarkDirty) { + buttonNode->MarkModifyDone(); + buttonNode->MarkDirtyNode(); + } +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/time_picker/timepicker_column_pattern.h b/frameworks/core/components_ng/pattern/time_picker/timepicker_column_pattern.h index f69a24b3cc0..84e85153726 100644 --- a/frameworks/core/components_ng/pattern/time_picker/timepicker_column_pattern.h +++ b/frameworks/core/components_ng/pattern/time_picker/timepicker_column_pattern.h @@ -137,10 +137,7 @@ public: enterSelectedAreaEventCallback_ = value; } - const Color& GetButtonHoverColor() const override - { - return hoverColor_; - } + const Color& GetButtonHoverColor() const override; const Color& GetButtonBgColor() const override { @@ -153,6 +150,8 @@ public: } std::string GetCurrentOption() const override; + + void UpdateColumnButtonFocusState(bool haveFocus, bool needMarkDirty); bool GetCanLoopFromLayoutProperty() const override; @@ -166,6 +165,8 @@ private: const RefPtr& timePickerLayoutProperty); void InitOnKeyEvent(const RefPtr& focusHub); + void InitSelectorButtonProperties(const RefPtr& pickerTheme); + void UpdateSelectorButtonProps(bool haveFocus, bool needMarkDirty); bool OnKeyEvent(const KeyEvent& event); bool HandleDirectionKey(KeyCode code); void UpdateSelectedTextColor(const RefPtr& pickerTheme) override; @@ -182,6 +183,7 @@ private: Color pressColor_; Color hoverColor_; Color buttonBgColor_ = Color::TRANSPARENT; + Color buttonFocusBgColor_ = Color::TRANSPARENT; bool hour24_ = SystemProperties::Is24HourClock(); // column options number std::map, uint32_t> optionsTotalCount_; @@ -198,6 +200,15 @@ private: bool hasUserDefinedNormalFontFamily_ = false; bool hasUserDefinedSelectedFontFamily_ = false; bool isTossReadyToStop_ = false; + Color buttonDefaultBgColor_ = Color::TRANSPARENT; + Color buttonDefaultBorderColor_ = Color::TRANSPARENT; + Color buttonFocusBorderColor_ = Color::TRANSPARENT; + Color selectorTextFocusColor_ = Color::WHITE; + Dimension buttonDefaultBorderWidth_ = 0.0_vp; + Dimension buttonFocusBorderWidth_ = 0.0_vp; + bool isFirstTimeUpdateButtonProps_ = true; + bool useButtonFocusArea_ = false; + bool isFocusColumn_ = false; ACE_DISALLOW_COPY_AND_MOVE(TimePickerColumnPattern); friend class PickerColumnPatternCircleUtils; }; diff --git a/frameworks/core/components_ng/pattern/time_picker/timepicker_row_pattern.cpp b/frameworks/core/components_ng/pattern/time_picker/timepicker_row_pattern.cpp index 1d329d96db2..674972a0ab2 100644 --- a/frameworks/core/components_ng/pattern/time_picker/timepicker_row_pattern.cpp +++ b/frameworks/core/components_ng/pattern/time_picker/timepicker_row_pattern.cpp @@ -98,6 +98,10 @@ void TimePickerRowPattern::SetButtonIdeaSize() CHECK_NULL_VOID(pickerTheme); auto children = host->GetChildren(); auto height = pickerTheme->GetDividerSpacing(); + auto currentFocusStackChild = DynamicCast(host->GetChildAtIndex(focusKeyID_)); + CHECK_NULL_VOID(currentFocusStackChild); + auto currentFocusButtonNode = DynamicCast(currentFocusStackChild->GetFirstChild()); + CHECK_NULL_VOID(currentFocusButtonNode); for (const auto& child : children) { auto childNode = DynamicCast(child); CHECK_NULL_VOID(childNode); @@ -120,7 +124,14 @@ void TimePickerRowPattern::SetButtonIdeaSize() buttonLayoutProperty->UpdateUserDefinedIdealSize( CalcSize(CalcLength(width - PRESS_INTERVAL.ConvertToPx()), CalcLength(buttonHeight))); auto buttonConfirmRenderContext = buttonNode->GetRenderContext(); - buttonConfirmRenderContext->UpdateBackgroundColor(Color::TRANSPARENT); + if (!useButtonFocusArea_) { + buttonConfirmRenderContext->UpdateBackgroundColor(Color::TRANSPARENT); + } else { + auto isFocusButton = haveFocus_ && (currentFocusButtonNode == buttonNode); + auto columnNode = DynamicCast(timePickerColumnNode->GetLastChild()); + CHECK_NULL_VOID(columnNode); + UpdateColumnButtonStyles(columnNode, isFocusButton, false); + } buttonNode->MarkModifyDone(); buttonNode->MarkDirtyNode(); if (GetIsShowInDialog() && GreatNotEqual(standardButtonHeight, maxButtonHeight) && @@ -132,6 +143,93 @@ void TimePickerRowPattern::SetButtonIdeaSize() } } +void TimePickerRowPattern::InitSelectorProps() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto context = host->GetContextRefPtr(); + CHECK_NULL_VOID(context); + auto pickerTheme = context->GetTheme(); + CHECK_NULL_VOID(pickerTheme); + useButtonFocusArea_ = pickerTheme->NeedButtonFocusAreaType(); +} + +void TimePickerRowPattern::AddIsFocusActiveUpdateEvent() +{ + if (!isFocusActiveUpdateEvent_) { + isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) { + auto pickerPattern = weak.Upgrade(); + CHECK_NULL_VOID(pickerPattern); + pickerPattern->SetHaveFocus(isFocusAcitve); + pickerPattern->UpdateFocusButtonState(); + }; + } + + auto context = GetContext(); + CHECK_NULL_VOID(context); + context->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_); +} + +void TimePickerRowPattern::RemoveIsFocusActiveUpdateEvent() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto pipeline = host->GetContext(); + CHECK_NULL_VOID(pipeline); + pipeline->RemoveIsFocusActiveUpdateEvent(host); +} + +void TimePickerRowPattern::SetHaveFocus(bool haveFocus) +{ + haveFocus_ = haveFocus; +} + +void TimePickerRowPattern::HandleFocusEvent() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto context = host->GetContextRefPtr(); + CHECK_NULL_VOID(context); + + AddIsFocusActiveUpdateEvent(); + if (context->GetIsFocusActive()) { + SetHaveFocus(true); + UpdateFocusButtonState(); + } +} + +void TimePickerRowPattern::HandleBlurEvent() +{ + SetHaveFocus(false); + RemoveIsFocusActiveUpdateEvent(); + UpdateFocusButtonState(); +} + +void TimePickerRowPattern::UpdateFocusButtonState() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); + if (useButtonFocusArea_) { + auto currentFocusStackNode = DynamicCast(host->GetChildAtIndex(focusKeyID_)); + CHECK_NULL_VOID(currentFocusStackNode); + auto blendColumnNode = currentFocusStackNode->GetLastChild(); + CHECK_NULL_VOID(blendColumnNode); + auto currentFocusColumnNode = DynamicCast(blendColumnNode->GetLastChild()); + CHECK_NULL_VOID(currentFocusColumnNode); + + UpdateColumnButtonStyles(currentFocusColumnNode, haveFocus_, true); + } +} + +void TimePickerRowPattern::UpdateColumnButtonStyles( + const RefPtr& columnNode, bool haveFocus, bool needMarkDirty) +{ + CHECK_NULL_VOID(columnNode); + auto datePickerColumnPattern = columnNode->GetPattern(); + CHECK_NULL_VOID(datePickerColumnPattern); + datePickerColumnPattern->UpdateColumnButtonFocusState(haveFocus, needMarkDirty); +} + void TimePickerRowPattern::ColumnPatternInitHapticController() { if (!isHapticChanged_) { @@ -298,12 +396,33 @@ void TimePickerRowPattern::InitFocusEvent() auto host = GetHost(); CHECK_NULL_VOID(host); auto focusHub = host->GetFocusHub(); + CHECK_NULL_VOID(focusHub); if (focusHub) { InitOnKeyEvent(focusHub); #ifdef SUPPORT_DIGITAL_CROWN InitOnCrownEvent(focusHub); #endif } + CHECK_NULL_VOID(!focusEventInitialized_); + auto context = host->GetContextRefPtr(); + CHECK_NULL_VOID(context); + auto pickerTheme = context->GetTheme(); + CHECK_NULL_VOID(pickerTheme); + auto focusTask = [weak = WeakClaim(this)](FocusReason reason) { + auto pattern = weak.Upgrade(); + CHECK_NULL_VOID(pattern); + pattern->HandleFocusEvent(); + }; + focusHub->SetOnFocusInternal(focusTask); + + auto blurTask = [weak = WeakClaim(this)]() { + auto pattern = weak.Upgrade(); + CHECK_NULL_VOID(pattern); + pattern->HandleBlurEvent(); + }; + focusHub->SetOnBlurInternal(blurTask); + + focusEventInitialized_ = true; } void TimePickerRowPattern::UpdateTitleNodeContent() @@ -376,6 +495,7 @@ void TimePickerRowPattern::OnModifyDone() UpdateUserSetSelectColor(); } SetDefaultFocus(); + InitSelectorProps(); } void TimePickerRowPattern::LimitSelectedTimeInRange() @@ -1873,6 +1993,7 @@ void TimePickerRowPattern::PaintFocusState() CHECK_NULL_VOID(focusHub); focusHub->PaintInnerFocusState(focusRect); + UpdateFocusButtonState(); host->MarkDirtyNode(PROPERTY_UPDATE_RENDER); } diff --git a/frameworks/core/components_ng/pattern/time_picker/timepicker_row_pattern.h b/frameworks/core/components_ng/pattern/time_picker/timepicker_row_pattern.h index bce32f325d6..4f84d4633e6 100644 --- a/frameworks/core/components_ng/pattern/time_picker/timepicker_row_pattern.h +++ b/frameworks/core/components_ng/pattern/time_picker/timepicker_row_pattern.h @@ -499,7 +499,6 @@ public: auto focusColor = pickerTheme->GetFocusColor(); FocusPaintParam focusPaintParams; focusPaintParams.SetPaintColor(focusColor); - focusPaintParams.SetPaintWidth(TIME_FOCUS_PAINT_WIDTH); return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION, focusPaintParams }; } @@ -766,6 +765,17 @@ private: void UpdateDialogAgingButton(const RefPtr& buttonNode, bool isNext); Dimension ConvertFontScaleValue(const Dimension& fontSizeValue); + void InitSelectorProps(); + void HandleFocusEvent(); + void HandleBlurEvent(); + void AddIsFocusActiveUpdateEvent(); + void RemoveIsFocusActiveUpdateEvent(); + void GetInnerFocusButtonPaintRect(RoundRect& paintRect, float focusButtonXOffset); + void UpdateFocusButtonState(); + void SetHaveFocus(bool haveFocus); + void UpdateColumnButtonStyles(const RefPtr& columnNode, bool haveFocus, bool needMarkDirty); + + void UpdateTextStyleCommon( const PickerTextStyle& textStyle, const TextStyle& defaultTextStyle, @@ -850,6 +860,11 @@ private: bool isUserSetSelectColor_ = false; bool isClearFocus_ = true; bool isDirectionSetByAr = false; + + bool focusEventInitialized_ = false; + bool haveFocus_ = false; + bool useButtonFocusArea_ = false; + std::function isFocusActiveUpdateEvent_; }; } // namespace OHOS::Ace::NG -- Gitee