!41628 【收编】【TextInput/Search】渐隐&&差异化配置——功能代码

Merge pull request !41628 from zhangwenbin00001/pr-textinput-0822-8-24
This commit is contained in:
openharmony_ci 2024-09-09 10:41:13 +00:00 committed by Gitee
commit c11a042d54
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
16 changed files with 896 additions and 56 deletions

View File

@ -91,6 +91,8 @@ static const std::set<std::string> stringAttrs = {
"textfield_accessibility_hide_password",
"rich_editor_show_handle",
"text_show_handle",
"list_fadeout_enable",
"text_fadeout_enable",
"slider_accessibility_selected",
"slider_accessibility_unselected",
"slider_accessibility_unselectedDesc",

View File

@ -92,6 +92,13 @@ public:
theme->symbolIconColor_ = pattern->GetAttr<Color>("search_symbol_icon_color", Color());
theme->searchSymbolId_ = themeConstants->GetSymbolByName("sys.symbol.magnifyingglass");
theme->cancelSymbolId_ = themeConstants->GetSymbolByName("sys.symbol.xmark");
theme->borderColor_ = pattern->GetAttr<Color>("search_border_color", Color());
theme->borderWidth_ = pattern->GetAttr<Dimension>("search_border_width", 0.0_vp);
theme->focusBgColor_ = pattern->GetAttr<Color>("search_focus_bg_color", Color());
theme->focusIconColor_ = pattern->GetAttr<Color>("search_focus_icon_color", Color());
theme->needFocusBox_ = static_cast<bool>(pattern->GetAttr<double>("search_need_focus_box", 0.0));
theme->cancelButtonStyle_ = static_cast<CancelButtonStyle>(
static_cast<int32_t>(pattern->GetAttr<double>("search_cancel_button_style", 2.0f)));
}
};
@ -257,6 +264,31 @@ public:
return symbolIconColor_;
}
const Color& GetBorderColor() const
{
return borderColor_;
}
const Dimension& GetBorderWidth() const
{
return borderWidth_;
}
const Color& GetFocusBgColor() const
{
return focusBgColor_;
}
const Color& GetFocusIconColor() const
{
return focusIconColor_;
}
bool NeedFocusBox() const
{
return needFocusBox_;
}
protected:
SearchTheme() = default;
@ -293,6 +325,11 @@ private:
uint32_t searchSymbolId_ = 0;
uint32_t cancelSymbolId_ = 0;
Color symbolIconColor_;
Color borderColor_;
Dimension borderWidth_;
Color focusBgColor_;
Color focusIconColor_;
bool needFocusBox_ = false;
};
} // namespace OHOS::Ace

View File

@ -69,6 +69,7 @@ public:
ParsePatternSubFirstPart(pattern, theme);
ParsePatternSubSecondPart(pattern, theme);
ParsePatternSubThirdPart(pattern, theme);
ParsePatternSubFourthPart(pattern, theme);
}
void ParsePatternSubFirstPart(const RefPtr<ThemeStyle>& pattern, const RefPtr<TextFieldTheme>& theme) const
@ -216,6 +217,22 @@ public:
theme->aiWriteAbilityName_ = pattern->GetAttr<std::string>("textfield_writting_ability_name", "");
}
void ParsePatternSubFourthPart(const RefPtr<ThemeStyle>& pattern, const RefPtr<TextFieldTheme>& theme) const
{
std::string isTextFadeout = pattern->GetAttr<std::string>("text_fadeout_enable", "");
theme->textFadeoutEnabled_ = isTextFadeout == "true";
theme->textInputBorderColor_ = pattern->GetAttr<Color>("text_input_border_color", Color());
theme->textInputBorderWidth_ = pattern->GetAttr<Dimension>("text_input_border_width", 0.0_vp);
theme->errorTextInputBorderWidth_ = pattern->GetAttr<Dimension>("error_text_input_border_width", 1.0_vp);
theme->textInputAndErrTipsSpacing_ =
pattern->GetAttr<Dimension>("text_input_and_error_tips_spacing", 8.0_vp);
theme->showPasswordIcon_ = static_cast<bool>(pattern->GetAttr<double>("show_icon_text_input", 1.0));
theme->hoverAndPressBgColorEnabled_ =
static_cast<uint32_t>(pattern->GetAttr<int>("textfield_hover_press_bg_color_enabled", 0));
theme->needFocusBox_ = static_cast<bool>(pattern->GetAttr<double>("text_input_need_focus_box", 0.0));
theme->focusPadding_ = pattern->GetAttr<Dimension>("text_input_focus_padding", 0.0_vp);
}
};
~TextFieldTheme() override = default;
@ -637,6 +654,52 @@ public:
{
return aiWriteAbilityName_;
}
bool TextFadeoutEnabled() const
{
return textFadeoutEnabled_;
}
const Dimension& GetTextInputWidth() const
{
return textInputBorderWidth_;
}
const Color& GetTextInputColor() const
{
return textInputBorderColor_;
}
const Dimension& GetTextInputAndErrTipsSpacing() const
{
return textInputAndErrTipsSpacing_;
}
bool IsShowPasswordIcon() const
{
return showPasswordIcon_;
}
bool GetHoverAndPressBgColorEnabled() const
{
return hoverAndPressBgColorEnabled_;
}
const Dimension& GetErrorTextInputBorderWidth() const
{
return errorTextInputBorderWidth_;
}
bool NeedFocusBox() const
{
return needFocusBox_;
}
const Dimension& GetFocusPadding() const
{
return focusPadding_;
}
protected:
TextFieldTheme() = default;
@ -736,6 +799,14 @@ private:
Color previewUnderlineColor_;
Color previewBoardColor_;
bool textFadeoutEnabled_ = false;
Dimension textInputBorderWidth_ = 0.0_vp;
Dimension textInputAndErrTipsSpacing_ = 8.0_vp;
Dimension errorTextInputBorderWidth_ = 1.0_vp;
Color textInputBorderColor_;
bool showPasswordIcon_ = true;
bool hoverAndPressBgColorEnabled_ = false;
std::string cancelButton_;
Dimension inlinePaddingRight_ = 12.0_vp;
@ -745,6 +816,8 @@ private:
std::string hiddenPasswordPromptInformation_;
std::string aiWriteBundleName_;
std::string aiWriteAbilityName_;
bool needFocusBox_ = false;
Dimension focusPadding_;
};
} // namespace OHOS::Ace

View File

@ -31,6 +31,7 @@
#include "core/components_ng/property/layout_constraint.h"
#include "core/components_ng/property/measure_utils.h"
#include "core/pipeline_ng/pipeline_context.h"
#include "core/components_ng/pattern/search/search_pattern.h"
namespace OHOS::Ace::NG {
namespace {
@ -421,7 +422,9 @@ double SearchLayoutAlgorithm::CalcSearchHeight(
searchHeightAdapt = std::max(searchHeightAdapt, CalcSearchAdaptHeight(layoutWrapper));
renderContext->SetClipToBounds(false);
} else {
renderContext->SetClipToBounds(true);
auto pattern = host->GetPattern<SearchPattern>();
CHECK_NULL_RETURN(pattern, 0.0);
renderContext->SetClipToBounds(!pattern->NeedFocusBox());
}
const auto& calcLayoutConstraint = layoutWrapper->GetLayoutProperty()->GetCalcLayoutConstraint();
@ -644,6 +647,7 @@ void SearchLayoutAlgorithm::LayoutCancelButton(const LayoutSearchParams& params)
{
auto dividerSideSpace = params.searchTheme->GetDividerSideSpace().ConvertToPx();
auto dividerWidth = params.searchTheme->GetSearchDividerWidth().ConvertToPx();
auto borderWidth = params.searchTheme->GetBorderWidth().ConvertToPx();
auto cancelButtonWrapper = params.layoutWrapper->GetOrCreateChildByIndex(CANCEL_BUTTON_INDEX);
CHECK_NULL_VOID(cancelButtonWrapper);
@ -677,7 +681,7 @@ void SearchLayoutAlgorithm::LayoutCancelButton(const LayoutSearchParams& params)
cancelButtonHorizontalOffset =
std::max(searchButtonHorizontalOffset - cancelButtonOffsetToSearchButton, 0.0);
} else {
cancelButtonHorizontalOffset = params.searchFrameWidth - cancelButtonFrameWidth;
cancelButtonHorizontalOffset = params.searchFrameWidth - cancelButtonFrameWidth - borderWidth;
}
}
auto cancelButtonOffset = OffsetF(cancelButtonHorizontalOffset, cancelButtonVerticalOffset);

View File

@ -75,6 +75,34 @@ RefPtr<TextFieldControllerBase> SearchModelNG::Create(const std::optional<std::s
return pattern->GetSearchController();
}
void SearchModelNG::UpdateSearchNodeBorderProps(const RefPtr<SearchNode> frameNode)
{
CHECK_NULL_VOID(frameNode);
auto pipeline = frameNode->GetContext();
CHECK_NULL_VOID(pipeline);
auto searchTheme = pipeline->GetTheme<SearchTheme>();
CHECK_NULL_VOID(searchTheme);
auto renderContext = frameNode->GetRenderContext();
CHECK_NULL_VOID(renderContext);
auto layoutProperty = frameNode->GetLayoutProperty<SearchLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
layoutProperty->UpdateCancelButtonStyle(searchTheme->GetCancelButtonStyle());
if (!layoutProperty->GetBorderWidthProperty()) {
if (!renderContext->HasBorderWidth()) {
BorderWidthProperty borderWidth;
borderWidth.SetBorderWidth(searchTheme->GetBorderWidth());
layoutProperty->UpdateBorderWidth(borderWidth);
renderContext->UpdateBorderWidth(borderWidth);
}
if (!renderContext->HasBorderColor()) {
BorderColorProperty borderColor;
borderColor.SetColor(searchTheme->GetBorderColor());
renderContext->UpdateBorderColor(borderColor);
}
}
}
RefPtr<SearchNode> SearchModelNG::CreateSearchNode(int32_t nodeId, const std::optional<std::string>& value,
const std::optional<std::string>& placeholder, const std::optional<std::string>& icon)
{
@ -107,7 +135,7 @@ RefPtr<SearchNode> SearchModelNG::CreateSearchNode(int32_t nodeId, const std::op
BorderRadiusProperty borderRadius { radius.GetX(), radius.GetY(), radius.GetY(), radius.GetX() };
renderContext->UpdateBorderRadius(borderRadius);
auto layoutProperty = frameNode->GetLayoutProperty<SearchLayoutProperty>();
UpdateSearchNodeBorderProps(frameNode);
auto textFieldFrameNode = AceType::DynamicCast<FrameNode>(frameNode->GetChildAtIndex(TEXTFIELD_INDEX));
auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
pattern->SetSearchController(textFieldPattern->GetTextFieldController());
@ -741,8 +769,9 @@ void SearchModelNG::CreateTextField(const RefPtr<SearchNode>& parentNode, const
textFieldLayoutProperty->UpdatePlaceholder(placeholder.value_or(""));
textFieldLayoutProperty->UpdateMaxLines(1);
textFieldLayoutProperty->UpdatePlaceholderMaxLines(1);
if (!textFieldPaintProperty || !textFieldPaintProperty->HasTextColorFlagByUser()) {
if (!hasTextFieldNode) {
textFieldLayoutProperty->UpdateTextColor(searchTheme->GetTextColor());
textFieldLayoutProperty->UpdatePlaceholderTextColor(searchTheme->GetPlaceholderColor());
}
}
pattern->SetTextFieldController(AceType::MakeRefPtr<TextFieldController>());
@ -750,6 +779,8 @@ void SearchModelNG::CreateTextField(const RefPtr<SearchNode>& parentNode, const
pattern->SetTextEditController(AceType::MakeRefPtr<TextEditController>());
pattern->InitSurfaceChangedCallback();
pattern->InitSurfacePositionChangedCallback();
pattern->SetTextFadeoutCapacity(true);
if (pipeline->GetHasPreviewTextOption()) {
pattern->SetSupportPreviewText(pipeline->GetSupportPreviewText());
}
@ -783,6 +814,7 @@ void SearchModelNG::TextFieldUpdateContext(const RefPtr<FrameNode>& frameNode)
BorderRadiusProperty borderRadius;
textFieldPaintProperty->UpdateBorderRadiusFlagByUser(borderRadius);
pattern->SetEnableTouchAndHoverEffect(true);
textFieldPaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
}

View File

@ -159,6 +159,7 @@ public:
private:
static RefPtr<SearchNode> CreateSearchNode(int32_t nodeId, const std::optional<std::string>& value,
const std::optional<std::string>& placeholder, const std::optional<std::string>& icon);
static void UpdateSearchNodeBorderProps(const RefPtr<SearchNode> frameNode);
static void CreateTextField(const RefPtr<SearchNode>& parentNode,
const std::optional<std::string>& placeholder, const std::optional<std::string>& value, bool hasTextFieldNode);
static void CreateButton(const RefPtr<SearchNode>& parentNode, bool hasButtonNode);

View File

@ -33,6 +33,7 @@
#include "core/components_ng/pattern/text/text_pattern.h"
#include "core/components_ng/pattern/text_field/text_field_pattern.h"
#include "core/event/touch_event.h"
#include "core/components/theme/app_theme.h"
namespace OHOS::Ace::NG {
@ -203,6 +204,7 @@ void SearchPattern::OnModifyDone()
layoutProperty->UpdateMargin(margin);
}
InitSearchTheme();
HandleBackgroundColor();
auto searchButton = layoutProperty->GetSearchButton();
@ -229,6 +231,11 @@ void SearchPattern::OnModifyDone()
CHECK_NULL_VOID(cancelButtonLayoutProperty);
cancelButtonLayoutProperty->UpdateLabel("");
cancelButtonFrameNode->MarkModifyDone();
InitAllEvent();
}
void SearchPattern::InitAllEvent()
{
InitButtonAndImageClickEvent();
InitCancelButtonClickEvent();
InitTextFieldValueChangeEvent();
@ -236,10 +243,14 @@ void SearchPattern::OnModifyDone()
InitTextFieldClickEvent();
InitButtonMouseAndTouchEvent();
HandleTouchableAndHitTestMode();
auto host = GetHost();
CHECK_NULL_VOID(host);
auto focusHub = host->GetFocusHub();
CHECK_NULL_VOID(focusHub);
InitOnKeyEvent(focusHub);
InitFocusEvent(focusHub);
InitHoverEvent();
InitTouchEvent();
InitClickEvent();
HandleEnabled();
SetAccessibilityAction();
@ -895,17 +906,42 @@ bool SearchPattern::OnKeyEvent(const KeyEvent& event)
}
}
void SearchPattern::PaintSearchFocusState()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
CHECK_NULL_VOID(textFieldFrameNode);
auto textFieldLayoutProperty = textFieldFrameNode->GetLayoutProperty<TextFieldLayoutProperty>();
CHECK_NULL_VOID(textFieldLayoutProperty);
if (textFieldLayoutProperty->GetTextColorValue(normalTextColor_) == normalTextColor_) {
textFieldLayoutProperty->UpdateTextColor(focusTextColor_);
isFocusTextColorSet_ = true;
}
if (textFieldLayoutProperty->GetPlaceholderTextColorValue(normalPlaceholderColor_) == normalPlaceholderColor_) {
textFieldLayoutProperty->UpdatePlaceholderTextColor(focusPlaceholderColor_);
isFocusPlaceholderColorSet_ = true;
}
}
void SearchPattern::PaintFocusState(bool recoverFlag)
{
TAG_LOGI(AceLogTag::ACE_SEARCH, "Focus Choice = %{public}d", static_cast<int>(focusChoice_));
auto host = GetHost();
CHECK_NULL_VOID(host);
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
if (renderContext->GetBackgroundColor().value_or(searchNormalColor_) == searchNormalColor_) {
renderContext->UpdateBackgroundColor(focusBgColor_);
isFocusBgColorSet_ = true;
}
auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
CHECK_NULL_VOID(textFieldFrameNode);
auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
CHECK_NULL_VOID(textFieldPattern);
if (focusChoice_ == FocusChoice::SEARCH) {
PaintSearchFocusState();
if (!recoverFlag) {
if (!textFieldPattern->GetTextValue().empty()) {
textFieldPattern->NeedRequestKeyboard();
@ -925,6 +961,10 @@ void SearchPattern::PaintFocusState(bool recoverFlag)
textFieldPattern->CloseKeyboard(true);
}
if (GetDefaultIconColor(IMAGE_INDEX) == normalIconColor_) {
SetSearchIconColor(focusIconColor_);
isFocusIconColorSet_ = true;
}
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
RoundRect focusRect;
@ -935,6 +975,30 @@ void SearchPattern::PaintFocusState(bool recoverFlag)
host->MarkModifyDone();
}
void SearchPattern::GetSearchFocusPaintRadius(
float& radiusTopLeft, float& radiusTopRight, float& radiusBottomLeft, float& radiusBottomRight)
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
auto radius = renderContext->GetBorderRadius();
if (radius.has_value()) {
if (radius->radiusTopLeft.has_value()) {
radiusTopLeft = static_cast<float>(radius->radiusTopLeft->ConvertToPx());
}
if (radius->radiusTopRight.has_value()) {
radiusTopRight = static_cast<float>(radius->radiusTopRight->ConvertToPx());
}
if (radius->radiusBottomLeft.has_value()) {
radiusBottomLeft = static_cast<float>(radius->radiusBottomLeft->ConvertToPx());
}
if (radius->radiusBottomRight.has_value()) {
radiusBottomRight = static_cast<float>(radius->radiusBottomRight->ConvertToPx());
}
}
}
void SearchPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
{
float originX = 0.0f;
@ -947,7 +1011,14 @@ void SearchPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
float radiusBottomRight = 0.0f;
float focusOffset = FOCUS_OFFSET.ConvertToPx();
if (focusChoice_ == FocusChoice::SEARCH) {
return;
if (!needFocusBox_) {
return;
}
originX = searchOffset_.GetX() - DOUBLE * focusOffset;
originY = searchOffset_.GetY() - DOUBLE * focusOffset;
endX = searchSize_.Width() + searchOffset_.GetX() + DOUBLE * focusOffset;
endY = searchSize_.Height() + searchOffset_.GetY() + DOUBLE * focusOffset;
GetSearchFocusPaintRadius(radiusTopLeft, radiusTopRight, radiusBottomLeft, radiusBottomRight);
}
if (focusChoice_ == FocusChoice::CANCEL_BUTTON) {
originX = cancelButtonOffset_.GetX() + focusOffset;
@ -1133,6 +1204,19 @@ void SearchPattern::AnimateTouchAndHover(RefPtr<RenderContext>& renderContext, f
option, [renderContext, highlightEnd]() { renderContext->OnBackgroundColorUpdate(highlightEnd); });
}
void SearchPattern::AnimateSearchTouchAndHover(RefPtr<RenderContext>& renderContext,
Color& blendColorFrom, Color& blendColorTo, int32_t duration, const RefPtr<Curve>& curve)
{
Color highlightStart = renderContext->GetBackgroundColor().value_or(Color::TRANSPARENT).BlendColor(blendColorFrom);
Color highlightEnd = renderContext->GetBackgroundColor().value_or(Color::TRANSPARENT).BlendColor(blendColorTo);
renderContext->OnBackgroundColorUpdate(highlightStart);
AnimationOption option = AnimationOption();
option.SetDuration(duration);
option.SetCurve(curve);
AnimationUtils::Animate(
option, [renderContext, highlightEnd]() { renderContext->OnBackgroundColorUpdate(highlightEnd); });
}
void SearchPattern::ResetDragOption()
{
ClearButtonStyle(BUTTON_INDEX);
@ -1150,6 +1234,99 @@ void SearchPattern::ClearButtonStyle(int32_t childId)
AnimateTouchAndHover(renderContext, TOUCH_OPACITY, 0.0f, HOVER_TO_TOUCH_DURATION, Curves::SHARP);
}
void SearchPattern::InitSearchTheme()
{
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto textFieldTheme = pipeline->GetTheme<TextFieldTheme>();
CHECK_NULL_VOID(textFieldTheme);
searchNormalColor_ = textFieldTheme->GetBgColor();
auto searchTheme = pipeline->GetTheme<SearchTheme>();
CHECK_NULL_VOID(searchTheme);
needFocusBox_ = searchTheme->NeedFocusBox();
searchHoverColor_ = searchTheme->GetHoverColor();
searchTouchColor_ = searchTheme->GetTouchColor();
focusBgColor_ = searchTheme->GetFocusBgColor();
focusIconColor_ = searchTheme->GetFocusIconColor();
normalTextColor_ = searchTheme->GetTextColor();
focusTextColor_ = searchTheme->GetFocusTextColor();
normalPlaceholderColor_ = searchTheme->GetPlaceholderColor();
focusPlaceholderColor_ = searchTheme->GetFocusPlaceholderColor();
normalIconColor_ = searchTheme->GetSymbolIconColor();
}
void SearchPattern::InitHoverEvent()
{
if (searchHoverListener_) {
return;
}
auto host = GetHost();
CHECK_NULL_VOID(host);
auto eventHub = host->GetEventHub<SearchEventHub>();
auto inputHub = eventHub->GetOrCreateInputEventHub();
auto mouseTask = [weak = WeakClaim(this)](bool isHover) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleHoverEvent(isHover);
};
searchHoverListener_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
inputHub->AddOnHoverEvent(searchHoverListener_);
}
void SearchPattern::HandleHoverEvent(bool isHover)
{
isSearchHover_ = isHover;
auto host = GetHost();
CHECK_NULL_VOID(host);
auto eventHub = host->GetEventHub<EventHub>();
CHECK_NULL_VOID(eventHub);
auto enabled = eventHub->IsEnabled();
auto inputEventHub = host->GetOrCreateInputEventHub();
auto hoverEffect = inputEventHub->GetHoverEffect();
if (hoverEffect == HoverEffectType::NONE || hoverEffect == HoverEffectType::SCALE) {
return;
}
if (!isSearchPress_ && (enabled || !isHover)) {
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
AnimateSearchTouchAndHover(renderContext, isHover ? transparentColor_ : searchHoverColor_,
isHover ? searchHoverColor_ : transparentColor_, HOVER_DURATION, Curves::FRICTION);
}
}
void SearchPattern::InitTouchEvent()
{
if (searchTouchListener_) {
return;
}
auto host = GetHost();
CHECK_NULL_VOID(host);
auto gesture = host->GetOrCreateGestureEventHub();
CHECK_NULL_VOID(gesture);
auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
auto infoTouches = info.GetTouches();
CHECK_EQUAL_VOID(infoTouches.empty(), true);
pattern->OnTouchDownOrUp(infoTouches.front().GetTouchType() == TouchType::DOWN);
};
searchTouchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
gesture->AddTouchEvent(searchTouchListener_);
}
void SearchPattern::OnTouchDownOrUp(bool isDown)
{
isSearchPress_ = isDown;
auto host = GetHost();
CHECK_NULL_VOID(host);
auto searchEventHub = GetEventHub<SearchEventHub>();
CHECK_NULL_VOID(searchEventHub);
auto renderContext = host->GetRenderContext();
AnimateSearchTouchAndHover(renderContext, isDown ? searchHoverColor_ : searchTouchColor_,
isDown ? searchTouchColor_ : searchHoverColor_, TOUCH_DURATION, Curves::FRICTION);
}
void SearchPattern::InitFocusEvent(const RefPtr<FocusHub>& focusHub)
{
auto focusTask = [weak = WeakClaim(this)]() {
@ -1202,8 +1379,28 @@ void SearchPattern::HandleBlurEvent()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
if (isFocusBgColorSet_) {
renderContext->UpdateBackgroundColor(searchNormalColor_);
isFocusBgColorSet_ = false;
}
if (isFocusIconColorSet_) {
SetSearchIconColor(normalIconColor_);
isFocusIconColorSet_ = false;
}
auto textFieldFrameNode = DynamicCast<FrameNode>(host->GetChildAtIndex(TEXTFIELD_INDEX));
CHECK_NULL_VOID(textFieldFrameNode);
auto textFieldLayoutProperty = textFieldFrameNode->GetLayoutProperty<TextFieldLayoutProperty>();
CHECK_NULL_VOID(textFieldLayoutProperty);
if (isFocusTextColorSet_) {
textFieldLayoutProperty->UpdateTextColor(normalTextColor_);
isFocusTextColorSet_ = false;
}
if (isFocusPlaceholderColorSet_) {
textFieldLayoutProperty->UpdatePlaceholderTextColor(normalPlaceholderColor_);
isFocusPlaceholderColorSet_ = false;
}
auto textFieldPattern = textFieldFrameNode->GetPattern<TextFieldPattern>();
CHECK_NULL_VOID(textFieldPattern);
textFieldPattern->HandleBlurEvent();
@ -1647,6 +1844,9 @@ void SearchPattern::UpdateSearchSymbolIconColor()
auto layoutProperty = cancelButtonFrameNode->GetLayoutProperty<TextLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
layoutProperty->UpdateSymbolColorList({ GetSearchNode()->GetSearchSymbolIconColor() });
if (isFocusIconColorSet_ && GetDefaultIconColor(IMAGE_INDEX) == normalIconColor_) {
SetSearchIconColor(focusIconColor_);
}
}
void SearchPattern::CreateCancelIcon()
@ -1838,6 +2038,32 @@ void SearchPattern::SetCancelButtonStyle(const CancelButtonStyle& style)
UpdateChangeEvent(textFieldPattern->GetTextValue(), static_cast<int16_t>(style));
}
Color SearchPattern::GetDefaultIconColor(int32_t index)
{
Color defaultIconColor = normalIconColor_;
CHECK_NULL_RETURN(GetSearchNode(), defaultIconColor);
auto iconFrameNode = AceType::DynamicCast<FrameNode>(GetSearchNode()->GetChildAtIndex(index));
CHECK_NULL_RETURN(iconFrameNode, defaultIconColor);
if (iconFrameNode->GetTag() == V2::SYMBOL_ETS_TAG) {
auto symbolLayoutProperty = iconFrameNode->GetLayoutProperty<TextLayoutProperty>();
CHECK_NULL_RETURN(symbolLayoutProperty, defaultIconColor);
std::vector<Color> symbolColorList = symbolLayoutProperty->GetSymbolColorListValue({ normalIconColor_ });
if (symbolColorList.size() >= 1) {
defaultIconColor = symbolColorList[0];
}
} else {
auto imageLayoutProperty = iconFrameNode->GetLayoutProperty<ImageLayoutProperty>();
CHECK_NULL_RETURN(imageLayoutProperty, defaultIconColor);
auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo().value();
if (imageSourceInfo.IsSvg()) {
auto imageRenderProperty = iconFrameNode->GetPaintProperty<ImageRenderProperty>();
CHECK_NULL_RETURN(imageRenderProperty, defaultIconColor);
defaultIconColor = imageRenderProperty->GetSvgFillColorValue(normalIconColor_);
}
}
return defaultIconColor;
}
void SearchPattern::SetCancelImageIcon(IconOptions& iconOptions)
{
CHECK_NULL_VOID(GetSearchNode());

View File

@ -190,6 +190,11 @@ public:
return buttonSize_;
}
bool NeedFocusBox() const
{
return needFocusBox_;
}
void ResetDragOption() override;
void OnColorConfigurationUpdate() override;
@ -235,6 +240,9 @@ private:
bool OnKeyEvent(const KeyEvent& event);
void PaintFocusState(bool recoverFlag = false);
void GetInnerFocusPaintRect(RoundRect& paintRect);
void PaintSearchFocusState();
void GetSearchFocusPaintRadius(float& radiusTopLeft, float& radiusTopRight,
float& radiusBottomLeft, float& radiusBottomRight);
void RequestKeyboard();
// Init touch and hover event
void InitTextFieldValueChangeEvent();
@ -263,6 +271,8 @@ private:
void AnimateTouchAndHover(RefPtr<RenderContext>& renderContext, float startOpacity, float endOpacity,
int32_t duration, const RefPtr<Curve>& curve);
void AnimateSearchTouchAndHover(RefPtr<RenderContext>& renderContext, Color& blendColorFrom, Color& blendColorTo,
int32_t duration, const RefPtr<Curve>& curve);
void InitFocusEvent(const RefPtr<FocusHub>& focusHub);
void HandleFocusEvent(bool forwardFocusMovement, bool backwardFocusMovement);
void HandleBlurEvent();
@ -270,6 +280,12 @@ private:
void HandleClickEvent(GestureEvent& info);
void UpdateIconChangeEvent();
bool IsEventEnabled(const std::string& textValue, int16_t style);
void InitAllEvent();
void InitHoverEvent();
void InitTouchEvent();
void InitSearchTheme();
void OnTouchDownOrUp(bool isDown);
void HandleHoverEvent(bool isHover);
void UpdateSearchSymbolIconColor();
void UpdateCancelSymbolIconColor();
@ -293,6 +309,7 @@ private:
void UpdateIconColor(int32_t index, const Color& color);
void UpdateIconSize(int32_t index, const Dimension& value);
const Dimension ConvertImageIconScaleLimit(const Dimension& fontSizeValue);
Color GetDefaultIconColor(int32_t index);
uint32_t GetMaxLength() const;
std::string SearchTypeToString() const;
@ -312,16 +329,36 @@ private:
RefPtr<TextFieldController> searchController_;
FocusChoice focusChoice_ = FocusChoice::SEARCH;
RefPtr<TouchEventImpl> searchTouchListener_;
RefPtr<TouchEventImpl> searchButtonTouchListener_;
RefPtr<TouchEventImpl> cancelButtonTouchListener_;
RefPtr<InputEvent> searchHoverListener_;
RefPtr<InputEvent> searchButtonMouseEvent_;
RefPtr<InputEvent> cancelButtonMouseEvent_;
RefPtr<InputEvent> textFieldHoverEvent_ = nullptr;
RefPtr<ClickEvent> clickListener_;
bool isSearchHover_ = false;
bool isSearchPress_ = false;
bool isCancelButtonHover_ = false;
bool isSearchButtonHover_ = false;
bool isSearchButtonEnabled_ = false;
bool needFocusBox_ = false;
bool isFocusPlaceholderColorSet_ = false;
bool isFocusBgColorSet_ = false;
bool isFocusIconColorSet_ = false;
bool isFocusTextColorSet_ = false;
Color searchHoverColor_;
Color searchTouchColor_;
Color searchNormalColor_;
Color focusBgColor_;
Color focusIconColor_;
Color normalIconColor_;
Color focusTextColor_;
Color normalTextColor_;
Color focusPlaceholderColor_;
Color normalPlaceholderColor_;
Color transparentColor_ = Color::TRANSPARENT;
WeakPtr<FrameNode> cancelButtonNode_;
WeakPtr<FrameNode> buttonNode_;

View File

@ -44,9 +44,9 @@ const FontWeight FONT_WEIGHT_CONVERT_MAP[] = {
FontWeight::W500,
FontWeight::W400,
};
constexpr Dimension ERROR_TEXT_UNDERLINE_MARGIN = 8.0_vp;
constexpr Dimension ERROR_TEXT_CAPSULE_MARGIN = 8.0_vp;
constexpr float ROUND_VALUE = 0.5f;
constexpr Dimension DEFAULT_FADEOUT_VP = 16.0_vp;
constexpr double MAX_TEXTFADEOUT_PERCENT = 0.5;
inline FontWeight ConvertFontWeight(FontWeight fontWeight)
{
@ -78,52 +78,13 @@ TextFieldContentModifier::TextFieldContentModifier(const WeakPtr<OHOS::Ace::NG::
void TextFieldContentModifier::onDraw(DrawingContext& context)
{
auto& canvas = context.canvas;
auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
CHECK_NULL_VOID(textFieldPattern);
auto paragraph = textFieldPattern->GetParagraph();
CHECK_NULL_VOID(paragraph);
auto contentOffset = contentOffset_->Get();
auto contentRect = textFieldPattern->GetContentRect();
auto clipRectHeight = 0.0f;
auto errorMargin = 0.0f;
auto frameNode = textFieldPattern->GetHost();
CHECK_NULL_VOID(frameNode);
auto layoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
if (layoutProperty->GetShowUnderlineValue(false) && showErrorState_->Get()) {
errorMargin = ERROR_TEXT_UNDERLINE_MARGIN.ConvertToPx();
} else if (textFieldPattern->NeedShowPasswordIcon() && showErrorState_->Get()) {
errorMargin = ERROR_TEXT_CAPSULE_MARGIN.ConvertToPx();
} else if (showErrorState_->Get()) {
errorMargin = ERROR_TEXT_CAPSULE_MARGIN.ConvertToPx();
if (textFieldPattern->IsInlineMode() || !textFadeoutEnabled_) {
DoNormalDraw(context);
} else {
errorMargin = 0;
DoTextFadeoutDraw(context);
}
ProcessErrorParagraph(context, errorMargin);
clipRectHeight = contentRect.GetY() + contentRect.Height();
canvas.Save();
RSRect clipInnerRect = RSRect(contentRect.GetX(), contentRect.GetY(),
contentRect.Width() + contentRect.GetX() + textFieldPattern->GetInlinePadding(), clipRectHeight);
canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
if (paragraph) {
auto textField = textFieldPattern->IsTextArea() ? "TextArea" : "TextInput";
ACE_LAYOUT_SCOPED_TRACE("[%s][id:%d] [Rect:%s]", textField, frameNode->GetId(), contentRect.ToString().c_str());
if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
canvas.Save();
RSRect clipRect;
std::vector<RSPoint> clipRadius;
GetFrameRectClip(clipRect, clipRadius);
canvas.ClipRoundRect(clipRect, clipRadius, true);
paragraph->Paint(canvas, textFieldPattern->GetTextRect().GetX(),
textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY());
canvas.Restore();
} else {
paragraph->Paint(canvas, textFieldPattern->GetTextRect().GetX(),
textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY());
}
}
canvas.Restore();
}
void TextFieldContentModifier::GetFrameRectClip(RSRect& clipRect, std::vector<RSPoint>& clipRadius)
@ -621,4 +582,163 @@ void TextFieldContentModifier::UpdateTextDecorationMeasureFlag(PropertyChangeFla
}
}
void TextFieldContentModifier::SetTextFadeoutEnabled(bool enabled)
{
textFadeoutEnabled_ = enabled;
}
void TextFieldContentModifier::SetErrorTipsSpacing(const Dimension& errTipsSpacing)
{
errorTipsSpacing_ = errTipsSpacing;
}
void TextFieldContentModifier::DoNormalDraw(DrawingContext& context)
{
auto& canvas = context.canvas;
auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
CHECK_NULL_VOID(textFieldPattern);
auto paragraph = textFieldPattern->GetParagraph();
CHECK_NULL_VOID(paragraph);
auto contentOffset = contentOffset_->Get();
auto contentRect = textFieldPattern->GetContentRect();
auto textRect = textFieldPattern->GetTextRect();
auto clipRectHeight = 0.0f;
auto errorMargin = 0.0f;
auto frameNode = textFieldPattern->GetHost();
CHECK_NULL_VOID(frameNode);
if (showErrorState_->Get()) {
errorMargin = errorTipsSpacing_.ConvertToPx();
} else {
errorMargin = 0;
}
ProcessErrorParagraph(context, errorMargin);
clipRectHeight = contentRect.GetY() + contentRect.Height();
canvas.Save();
RSRect clipInnerRect = RSRect(contentRect.GetX(), contentRect.GetY(),
contentRect.Width() + contentRect.GetX() + textFieldPattern->GetInlinePadding(), clipRectHeight);
canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
if (paragraph) {
auto textField = textFieldPattern->IsTextArea() ? "TextArea" : "TextInput";
ACE_LAYOUT_SCOPED_TRACE("[%s][id:%d] [Rect:%s]", textField, frameNode->GetId(), contentRect.ToString().c_str());
if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
canvas.Save();
RSRect clipRect;
std::vector<RSPoint> clipRadius;
GetFrameRectClip(clipRect, clipRadius);
canvas.ClipRoundRect(clipRect, clipRadius, true);
paragraph->Paint(
canvas, textRect.GetX(), textFieldPattern->IsTextArea() ? textRect.GetY() : contentOffset.GetY());
canvas.Restore();
} else {
paragraph->Paint(
canvas, textRect.GetX(), textFieldPattern->IsTextArea() ? textRect.GetY() : contentOffset.GetY());
}
}
canvas.Restore();
}
void TextFieldContentModifier::DoTextFadeoutDraw(DrawingContext& context)
{
auto& canvas = context.canvas;
auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
CHECK_NULL_VOID(textFieldPattern);
auto paragraph = textFieldPattern->GetParagraph();
CHECK_NULL_VOID(paragraph);
auto contentRect = textFieldPattern->GetContentRect();
auto clipRectHeight = 0.0f;
auto errorMargin = 0.0f;
auto errorViewHeight = 0.0f;
auto errorParagraph = textFieldPattern->GetErrorParagraph();
auto textFrameRect = textFieldPattern->GetFrameRect();
if (showErrorState_->Get()) {
errorMargin = errorTipsSpacing_.ConvertToPx();
} else {
errorMargin = 0;
}
ProcessErrorParagraph(context, errorMargin);
if (errorParagraph && showErrorState_->Get()) {
errorViewHeight = textFrameRect.Bottom() - textFrameRect.Top() + errorMargin;
}
clipRectHeight = contentRect.GetY() + contentRect.Height() + errorViewHeight;
RSRect clipInnerRect = RSRect(contentRect.GetX(), contentRect.GetY(),
contentRect.Width() + contentRect.GetX() + textFieldPattern->GetInlinePadding(), clipRectHeight);
RSSaveLayerOps slo(&clipInnerRect, nullptr);
canvas.SaveLayer(slo);
DrawTextFadeout(context);
canvas.Restore();
}
void TextFieldContentModifier::DrawTextFadeout(DrawingContext& context)
{
auto& canvas = context.canvas;
auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
CHECK_NULL_VOID(textFieldPattern);
auto frameNode = textFieldPattern->GetHost();
CHECK_NULL_VOID(frameNode);
auto paragraph = textFieldPattern->GetParagraph();
CHECK_NULL_VOID(paragraph);
auto contentOffset = contentOffset_->Get();
auto contentRect = frameNode->GetGeometryNode()->GetContentRect();
auto contentRectX = contentRect.GetX();
auto textRect = textFieldPattern->GetTextRect();
auto textRectX = textRect.GetX();
auto textWidth = paragraph->GetTextWidth();
auto leftFadeOn = false;
auto rigthFadeOn = false;
auto textFadeoutWidth = DEFAULT_FADEOUT_VP.ConvertToPx();
auto gradientPercent = std::min(MAX_TEXTFADEOUT_PERCENT,
textFadeoutWidth / std::max(static_cast<double>(contentRect.Width()), textFadeoutWidth));
auto textFadeRect = RectF(contentRect.GetX(), contentOffset.GetY(), contentRect.Width(),
std::max(textRect.Height(), contentRect.Height()));
AdjustTextFadeRect(textFadeRect);
RSRect clipRect;
std::vector<RSPoint> clipRadius;
GetFrameRectClip(clipRect, clipRadius);
canvas.ClipRoundRect(clipRect, clipRadius, true);
canvas.Save();
RSRect clipTextInnerRect = RSRect(textFadeRect.GetX(), textFadeRect.GetY(),
textFadeRect.Width() + textFadeRect.GetX(), textFadeRect.GetY() + textFadeRect.Height());
canvas.ClipRect(clipTextInnerRect, RSClipOp::INTERSECT);
paragraph->Paint(canvas, textRectX, contentOffset.GetY());
canvas.Restore();
auto textIndent = std::max(textFieldPattern->GetTextParagraphIndent(), 0.0f);
if (GreatNotEqual(textWidth + textIndent, contentRect.Width())) {
leftFadeOn = LessNotEqual(textRectX, contentRectX);
rigthFadeOn = GreatNotEqual((textRectX + textWidth + textIndent), contentRect.Right());
}
UpdateTextFadeout(canvas, textFadeRect, gradientPercent, leftFadeOn, rigthFadeOn);
}
void TextFieldContentModifier::AdjustTextFadeRect(RectF& textFadeRect)
{
const float TEXT_FADE_ADJUST_PX = 1;
textFadeRect -= OffsetF(TEXT_FADE_ADJUST_PX, TEXT_FADE_ADJUST_PX);
textFadeRect += SizeF((TEXT_FADE_ADJUST_PX + TEXT_FADE_ADJUST_PX), (TEXT_FADE_ADJUST_PX + TEXT_FADE_ADJUST_PX));
}
void TextFieldContentModifier::UpdateTextFadeout(
RSCanvas& canvas, const RectF& textRect, float gradientPercent, bool leftFade, bool rightFade)
{
RSBrush brush;
std::vector<RSPoint> points = { RSPoint(textRect.Left(), textRect.Top()),
RSPoint(textRect.Right(), textRect.Top()) };
std::vector<RSColorQuad> colors = { Color::TRANSPARENT.GetValue(), Color::WHITE.GetValue(), Color::WHITE.GetValue(),
Color::TRANSPARENT.GetValue() };
float leftEndPercent = leftFade ? gradientPercent : 0;
float rightStartPercent = rightFade ? (1.0f - gradientPercent) : 1.0f;
std::vector<RSScalar> pos = { 0.0f, leftEndPercent, rightStartPercent, 1.0f };
brush.SetShaderEffect(
RSShaderEffect::CreateLinearGradient(points.at(0), points.at(1), colors, pos, RSTileMode::CLAMP));
brush.SetBlendMode(RSBlendMode::DST_IN);
RSRect textFadeoutRect = RSRect(textRect.Left(), textRect.Top(), textRect.Right(), textRect.Bottom());
canvas.AttachBrush(brush);
canvas.DrawRect(textFadeoutRect);
canvas.DetachBrush();
}
} // namespace OHOS::Ace::NG

View File

@ -64,6 +64,8 @@ public:
void SetTextOverflow(const TextOverflow value);
void SetTextDecoration(const TextDecoration& value, const Color& color, const TextDecorationStyle& style);
void ContentChange();
void SetTextFadeoutEnabled(bool enabled);
void SetErrorTipsSpacing(const Dimension& errTipsSpacing);
private:
void SetDefaultFontSize(const TextStyle& textStyle);
@ -79,6 +81,12 @@ private:
void ProcessErrorParagraph(DrawingContext& context, float errorMargin);
void ModifyDecorationInTextStyle(TextStyle& textStyle);
void UpdateTextDecorationMeasureFlag(PropertyChangeFlag& flag);
void DoNormalDraw(DrawingContext& context);
void DoTextFadeoutDraw(DrawingContext& context);
void DrawTextFadeout(DrawingContext& context);
void UpdateTextFadeout(
RSCanvas& canvas, const RectF& textRect, float gradientPercent, bool leftFade, bool rightFade);
void AdjustTextFadeRect(RectF& textFadeRect);
WeakPtr<Pattern> pattern_;
RefPtr<PropertyString> fontFamilyString_;
@ -122,6 +130,9 @@ private:
RefPtr<PropertyBool> fontReady_;
RefPtr<PropertyInt> textOverflow_;
bool textFadeoutEnabled_ { false };
Dimension errorTipsSpacing_ = 0.0_vp;
ACE_DISALLOW_COPY_AND_MOVE(TextFieldContentModifier);
};
} // namespace OHOS::Ace::NG

View File

@ -69,6 +69,11 @@ public:
return unitWidth_;
}
float GetTextIndent() const
{
return indent_;
}
InlineMeasureItem GetInlineMeasureItem() const
{
return inlineMeasureItem_;

View File

@ -85,6 +85,7 @@ void TextFieldModelNG::CreateNode(
CHECK_NULL_VOID(textFieldTheme);
textfieldPaintProperty->UpdatePressBgColor(textFieldTheme->GetPressColor());
textfieldPaintProperty->UpdateHoverBgColor(textFieldTheme->GetHoverColor());
pattern->SetHoverPressBgColorEnabled(textFieldTheme->GetHoverAndPressBgColorEnabled());
SetCaretColor(textFieldTheme->GetCursorColor());
CaretStyle caretStyle;
caretStyle.caretWidth = textFieldTheme->GetCursorWidth();

View File

@ -117,6 +117,7 @@ void TextFieldPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
!textFieldPattern->IsNormalInlineState());
textFieldContentModifier_->SetErrorTextValue(layoutProperty->GetErrorTextValue(""));
textFieldContentModifier_->SetShowUnderlineState(layoutProperty->GetShowUnderlineValue(false));
DoTextRaceIfNeed(paintWrapper);
PropertyChangeFlag flag = 0;
if (textFieldContentModifier_->NeedMeasureUpdate(flag)) {
frameNode->MarkDirtyNode(flag);
@ -199,6 +200,28 @@ void TextFieldPaintMethod::UpdateOverlayModifier(PaintWrapper* paintWrapper)
UpdateScrollBar();
}
void TextFieldPaintMethod::DoTextRaceIfNeed(PaintWrapper* paintWrapper)
{
CHECK_NULL_VOID(paintWrapper);
CHECK_NULL_VOID(textFieldContentModifier_);
auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
CHECK_NULL_VOID(textFieldPattern);
auto textFieldTheme = textFieldPattern->GetTheme();
CHECK_NULL_VOID(textFieldTheme);
auto frameNode = textFieldPattern->GetHost();
CHECK_NULL_VOID(frameNode);
textFieldContentModifier_->SetErrorTipsSpacing(textFieldTheme->GetTextInputAndErrTipsSpacing());
if ((textFieldTheme->TextFadeoutEnabled() && textFieldPattern->GetTextFadeoutCapacity())) {
auto paragraph = textFieldPattern->GetParagraph();
CHECK_NULL_VOID(paragraph);
auto paintContentWidth = paintWrapper->GetContentSize().Width();
auto textFadeoutEnabled =
GreatNotEqual(paintContentWidth, 0.0) &&
GreatNotEqual(paragraph->GetTextWidth() + textFieldPattern->GetTextParagraphIndent(), paintContentWidth);
textFieldContentModifier_->SetTextFadeoutEnabled(textFadeoutEnabled);
}
}
void TextFieldPaintMethod::UpdateScrollBar()
{
auto scrollBar = scrollBar_.Upgrade();

View File

@ -57,6 +57,8 @@ public:
private:
void UpdateTextStyleToModifier(
const RefPtr<TextFieldLayoutProperty>& layoutProperty, const RefPtr<TextFieldTheme>& theme, bool isDisabled);
void DoTextRaceIfNeed(PaintWrapper* paintWrapper);
private:
WeakPtr<Pattern> pattern_;
RefPtr<TextFieldOverlayModifier> textFieldOverlayModifier_;

View File

@ -111,7 +111,6 @@ const BorderRadiusProperty ZERO_BORDER_RADIUS_PROPERTY(0.0_vp);
// need to be moved to TextFieldTheme
constexpr Dimension BORDER_DEFAULT_WIDTH = 0.0_vp;
constexpr Dimension TYPING_UNDERLINE_WIDTH = 2.0_px;
constexpr Dimension ERROR_BORDER_WIDTH = 1.0_vp;
constexpr Dimension OVER_COUNT_BORDER_WIDTH = 1.0_vp;
constexpr Dimension INLINE_BORDER_WIDTH = 2.0_vp;
constexpr Dimension ERROR_UNDERLINE_WIDTH = 2.0_px;
@ -164,6 +163,7 @@ constexpr int32_t PREVIEW_BAD_PARAMETERS = -1;
constexpr double MINIMAL_OFFSET = 0.01f;
constexpr float RICH_DEFAULT_SHADOW_COLOR = 0x33000000;
constexpr float RICH_DEFAULT_ELEVATION = 120.0f;
constexpr int32_t HOVER_ANIMATION_DURATION = 250;
static std::unordered_map<TextContentType, std::pair<AceAutoFillType, std::string>> contentTypeMap_ = {
{TextContentType::VISIBLE_PASSWORD,
@ -543,6 +543,7 @@ bool TextFieldPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dir
}
SetAccessibilityClearAction();
SetAccessibilityPasswordIconAction();
textParagraphIndent_ = textFieldLayoutAlgorithm->GetTextIndent();
return true;
}
@ -914,10 +915,104 @@ void TextFieldPattern::HandleFocusEvent()
}
ProcessFocusStyle();
RequestKeyboardByFocusSwitch();
SetFocusStyle();
AddIsFocusActiveUpdateEvent();
host->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity<float>()) <= 1 ?
PROPERTY_UPDATE_MEASURE_SELF : PROPERTY_UPDATE_MEASURE);
}
void TextFieldPattern::SetFocusStyle()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
CHECK_NULL_VOID(paintProperty);
auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
auto textFieldTheme = GetTheme();
CHECK_NULL_VOID(textFieldTheme);
if (!paintProperty->HasBackgroundColor() && !IsUnderlineMode()) {
auto defaultBGColor = textFieldTheme->GetBgColor();
if (paintProperty->GetBackgroundColorValue(defaultBGColor) == defaultBGColor) {
renderContext->UpdateBackgroundColor(textFieldTheme->GetFocusBgColor());
isFocusBGColorSet_ = true;
}
}
auto defaultTextColor = textFieldTheme->GetTextColor();
if (layoutProperty->GetTextColorValue(defaultTextColor) == defaultTextColor) {
layoutProperty->UpdateTextColor(textFieldTheme->GetFocusTextColor());
isFocusTextColorSet_ = true;
}
auto defaultPlaceholderColor = textFieldTheme->GetPlaceholderColor();
if (layoutProperty->GetPlaceholderTextColorValue(defaultPlaceholderColor) == defaultPlaceholderColor) {
layoutProperty->UpdatePlaceholderTextColor(textFieldTheme->GetFocusPlaceholderColor());
isFocusPlaceholderColorSet_ = true;
}
host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
}
void TextFieldPattern::ClearFocusStyle()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
CHECK_NULL_VOID(paintProperty);
auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
auto textFieldTheme = GetTheme();
CHECK_NULL_VOID(textFieldTheme);
if (isFocusBGColorSet_) {
renderContext->UpdateBackgroundColor(textFieldTheme->GetBgColor());
isFocusBGColorSet_ = false;
}
if (isFocusTextColorSet_) {
layoutProperty->UpdateTextColor(textFieldTheme->GetTextColor());
isFocusTextColorSet_ = false;
}
if (isFocusPlaceholderColorSet_) {
layoutProperty->UpdatePlaceholderTextColor(textFieldTheme->GetPlaceholderColor());
isFocusPlaceholderColorSet_ = false;
}
host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
}
void TextFieldPattern::AddIsFocusActiveUpdateEvent()
{
if (!isFocusActiveUpdateEvent_) {
isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->OnIsFocusActiveUpdate(isFocusAcitve);
};
}
auto pipline = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(pipline);
pipline->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
}
void TextFieldPattern::RemoveIsFocusActiveUpdateEvent()
{
auto pipline = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(pipline);
pipline->RemoveIsFocusActiveUpdateEvent(GetHost());
}
void TextFieldPattern::OnIsFocusActiveUpdate(bool isFocusAcitve)
{
if (isFocusAcitve) {
SetFocusStyle();
} else {
ClearFocusStyle();
}
}
void TextFieldPattern::ProcessFocusStyle()
{
bool needTwinkling = true;
@ -1249,6 +1344,8 @@ void TextFieldPattern::HandleBlurEvent()
isCursorAlwaysDisplayed_ = false;
ReportEvent();
ScheduleDisappearDelayTask();
ClearFocusStyle();
RemoveIsFocusActiveUpdateEvent();
}
void TextFieldPattern::ModifyInnerStateInBlurEvent()
@ -1684,6 +1781,7 @@ void TextFieldPattern::HandleTouchEvent(const TouchEventInfo& info)
void TextFieldPattern::HandleTouchDown(const Offset& offset)
{
UpdatePressStyle(true);
moveCaretState_.touchDownOffset = offset;
if (HasStateStyle(UI_STATE_PRESSED)) {
return;
@ -1698,6 +1796,7 @@ void TextFieldPattern::HandleTouchDown(const Offset& offset)
void TextFieldPattern::HandleTouchUp()
{
UpdatePressStyle(false);
if (GetIsPreviewText() && isTouchPreviewText_) {
StartTwinkling();
}
@ -2681,6 +2780,7 @@ void TextFieldPattern::OnModifyDone()
CHECK_NULL_VOID(layoutProperty);
auto textFieldTheme = GetTheme();
CHECK_NULL_VOID(textFieldTheme);
InitTextFieldThemeColors(textFieldTheme);
auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
CHECK_NULL_VOID(paintProperty);
CheckIfNeedToResetKeyboard();
@ -3264,9 +3364,83 @@ void TextFieldPattern::OnHover(bool isHover)
pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT, windowId);
pipeline->FreeMouseStyleHoldNode(frameId);
}
UpdateHoverStyle(isHover);
isOnHover_ = isHover;
}
void TextFieldPattern::InitTextFieldThemeColors(const RefPtr<TextFieldTheme>& theme)
{
CHECK_NULL_VOID(theme);
defaultThemeBgColor_ = theme->GetBgColor();
focusThemeBgColor_ = theme->GetFocusBgColor();
hoverThemeBgColor_ = theme->GetPressColor();
pressThemeBgColor_ = theme->GetHoverColor();
}
void TextFieldPattern::UpdateHoverStyle(bool isHover)
{
if (hoverAndPressBgColorEnabled_) {
auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
CHECK_NULL_VOID(paintProperty);
auto textFieldBgColor = paintProperty->GetBackgroundColorValue(defaultThemeBgColor_);
auto bgColor = textFieldBgColor == defaultThemeBgColor_
? (IsUnderlineMode() ? Color::TRANSPARENT : defaultThemeBgColor_)
: textFieldBgColor;
auto hoverColor = bgColor.BlendColor(hoverThemeBgColor_);
if (!HasFocus()) {
if (isHover) {
PlayAnimationHoverAndPress(hoverColor);
} else {
PlayAnimationHoverAndPress(bgColor);
}
}
}
}
void TextFieldPattern::UpdatePressStyle(bool isPressed)
{
if (hoverAndPressBgColorEnabled_) {
auto paintProperty = GetPaintProperty<TextFieldPaintProperty>();
CHECK_NULL_VOID(paintProperty);
auto textFieldBgColor = paintProperty->GetBackgroundColorValue(defaultThemeBgColor_);
auto bgColor =
textFieldBgColor == defaultThemeBgColor_
? (IsUnderlineMode() ? Color::TRANSPARENT : (HasFocus() ? focusThemeBgColor_ : defaultThemeBgColor_))
: textFieldBgColor;
auto pressColor = bgColor.BlendColor(pressThemeBgColor_);
if (isPressed) {
PlayAnimationHoverAndPress(pressColor);
} else {
PlayAnimationHoverAndPress(bgColor);
}
}
}
void TextFieldPattern::PlayAnimationHoverAndPress(const Color& color)
{
AnimationOption option = AnimationOption();
option.SetDuration(HOVER_ANIMATION_DURATION);
option.SetCurve(Curves::FRICTION);
AnimationUtils::Animate(option, [weak = AceType::WeakClaim(this), color]() {
auto textFieldPattern = weak.Upgrade();
CHECK_NULL_VOID(textFieldPattern);
textFieldPattern->UpdateTextFieldBgColor(color);
});
}
void TextFieldPattern::UpdateTextFieldBgColor(const Color& color)
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
renderContext->UpdateBackgroundColor(color);
host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
}
void TextFieldPattern::RestoreDefaultMouseState()
{
int32_t windowId = 0;
@ -5804,7 +5978,7 @@ void TextFieldPattern::SetShowError()
} else if (passWordMode) {
BorderWidthProperty borderWidth;
BorderColorProperty borderColor;
borderWidth.SetBorderWidth(ERROR_BORDER_WIDTH);
borderWidth.SetBorderWidth(textFieldTheme->GetErrorTextInputBorderWidth());
layoutProperty->UpdateBorderWidth(borderWidth);
borderColor.SetColor(textFieldTheme->GetPasswordErrorBorderColor());
renderContext->UpdateBorderColor(borderColor);
@ -7024,7 +7198,10 @@ bool TextFieldPattern::IsShowPasswordIcon() const
{
auto layoutProperty = GetLayoutProperty<TextFieldLayoutProperty>();
CHECK_NULL_RETURN(layoutProperty, false);
return layoutProperty->GetShowPasswordIconValue(true) && IsInPasswordMode();
auto textfieldTheme = GetTheme();
CHECK_NULL_RETURN(textfieldTheme, false);
bool isShowPasswordIcon = textfieldTheme->IsShowPasswordIcon();
return layoutProperty->GetShowPasswordIconValue(isShowPasswordIcon) && IsInPasswordMode();
}
std::optional<bool> TextFieldPattern::IsShowPasswordText() const
@ -7252,9 +7429,45 @@ void TextFieldPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
auto unitRect = unitNode->GetGeometryNode()->GetFrameRect();
paintRect.SetRect(unitRect);
}
} else {
GetTextInputFocusPaintRect(paintRect);
}
}
void TextFieldPattern::GetTextInputFocusPaintRect(RoundRect& paintRect)
{
auto textfieldTheme = GetTheme();
CHECK_NULL_VOID(textfieldTheme);
auto isNeedFocusBox = textfieldTheme->NeedFocusBox();
if (!isNeedFocusBox) {
return;
}
auto host = GetHost();
CHECK_NULL_VOID(host);
auto geometryNode = host->GetGeometryNode();
CHECK_NULL_VOID(geometryNode);
auto textInputSize = geometryNode->GetFrameSize();
auto focusPaintPadding = textfieldTheme->GetFocusPadding().ConvertToPx();
float width = textInputSize.Width() + 2 * focusPaintPadding;
float height = textInputSize.Height() + 2 * focusPaintPadding;
paintRect.SetRect({ -focusPaintPadding, -focusPaintPadding, width, height });
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
auto radius = renderContext->GetBorderRadius().value_or(BorderRadiusProperty());
paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS,
static_cast<float>(radius.radiusTopLeft->ConvertToPx() + focusPaintPadding),
static_cast<float>(radius.radiusTopLeft->ConvertToPx() + focusPaintPadding));
paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS,
static_cast<float>(radius.radiusTopRight->ConvertToPx() + focusPaintPadding),
static_cast<float>(radius.radiusTopRight->ConvertToPx() + focusPaintPadding));
paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS,
static_cast<float>(radius.radiusBottomLeft->ConvertToPx() + focusPaintPadding),
static_cast<float>(radius.radiusBottomLeft->ConvertToPx() + focusPaintPadding));
paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS,
static_cast<float>(radius.radiusBottomRight->ConvertToPx() + focusPaintPadding),
static_cast<float>(radius.radiusBottomRight->ConvertToPx() + focusPaintPadding));
}
void TextFieldPattern::PaintCancelRect()
{
RoundRect focusRect;
@ -7604,7 +7817,7 @@ void TextFieldPattern::SetThemeBorderAttr()
CHECK_NULL_VOID(theme);
if (!paintProperty->HasBorderColorFlagByUser()) {
BorderColorProperty borderColor;
borderColor.SetColor(Color::BLACK);
borderColor.SetColor(theme->GetTextInputColor());
renderContext->UpdateBorderColor(borderColor);
} else {
renderContext->UpdateBorderColor(paintProperty->GetBorderColorFlagByUserValue());
@ -7621,7 +7834,7 @@ void TextFieldPattern::SetThemeBorderAttr()
if (!paintProperty->HasBorderWidthFlagByUser()) {
BorderWidthProperty borderWidth;
borderWidth.SetBorderWidth(BORDER_DEFAULT_WIDTH);
borderWidth.SetBorderWidth(theme->GetTextInputWidth());
renderContext->UpdateBorderWidth(borderWidth);
layoutProperty->UpdateBorderWidth(borderWidth);
} else {
@ -7644,7 +7857,8 @@ void TextFieldPattern::SetThemeAttr()
CHECK_NULL_VOID(theme);
SetThemeBorderAttr();
if (!paintProperty->HasBackgroundColor()) {
auto backgroundColor = IsUnderlineMode() ? Color::TRANSPARENT : theme->GetBgColor();
auto backgroundColor = isFocusBGColorSet_ ? theme->GetFocusBgColor() : theme->GetBgColor();
backgroundColor = IsUnderlineMode() ? Color::TRANSPARENT : backgroundColor;
renderContext->UpdateBackgroundColor(backgroundColor);
} else {
renderContext->UpdateBackgroundColor(paintProperty->GetBackgroundColorValue());
@ -7671,7 +7885,8 @@ void TextFieldPattern::SetThemeAttr()
}
if (!paintProperty->HasTextColorFlagByUser()) {
layoutProperty->UpdateTextColor(theme->GetTextColor());
auto textColor = isFocusTextColorSet_ ? theme->GetFocusTextColor() : theme->GetTextColor();
layoutProperty->UpdateTextColor(textColor);
} else {
layoutProperty->UpdateTextColor(paintProperty->GetTextColorFlagByUserValue());
}

View File

@ -71,6 +71,7 @@
#include "core/components_ng/pattern/text_field/text_selector.h"
#include "core/components_ng/pattern/text_input/text_input_layout_algorithm.h"
#include "core/components_ng/property/property.h"
#include "core/components/theme/app_theme.h"
#if not defined(ACE_UNITTEST)
#if defined(ENABLE_STANDARD_INPUT)
@ -358,6 +359,13 @@ public:
{
FocusPattern focusPattern = { FocusType::NODE, true, FocusStyleType::FORCE_NONE };
focusPattern.SetIsFocusActiveWhenFocused(true);
auto pipelineContext = PipelineBase::GetCurrentContext();
CHECK_NULL_RETURN(pipelineContext, focusPattern);
auto theme = pipelineContext->GetTheme<TextFieldTheme>();
CHECK_NULL_RETURN(theme, focusPattern);
if (theme->NeedFocusBox()) {
focusPattern.SetStyleType(FocusStyleType::OUTER_BORDER);
}
return focusPattern;
}
void PerformAction(TextInputAction action, bool forceCloseKeyboard = false) override;
@ -534,6 +542,11 @@ public:
textRect_ = textRect;
}
float GetTextParagraphIndent() const
{
return textParagraphIndent_;
}
const RectF& GetFrameRect() const
{
return frameRect_;
@ -882,6 +895,11 @@ public:
const std::optional<SelectionOptions>& options = std::nullopt, bool isForward = false);
void HandleBlurEvent();
void HandleFocusEvent();
void SetFocusStyle();
void ClearFocusStyle();
void AddIsFocusActiveUpdateEvent();
void RemoveIsFocusActiveUpdateEvent();
void OnIsFocusActiveUpdate(bool isFocusAcitve);
void ProcessFocusStyle();
bool OnBackPressed() override;
void CheckScrollable();
@ -1025,6 +1043,7 @@ public:
void SetTextInputFlag(bool isTextInput)
{
isTextInput_ = isTextInput;
SetTextFadeoutCapacity(isTextInput_);
}
void SetSingleLineHeight(float height)
@ -1425,6 +1444,20 @@ public:
adaptFontSize_ = adaptFontSize;
}
void SetTextFadeoutCapacity(bool enabled)
{
haveTextFadeoutCapacity_ = enabled;
}
bool GetTextFadeoutCapacity()
{
return haveTextFadeoutCapacity_;
}
void SetHoverPressBgColorEnabled(bool enabled)
{
hoverAndPressBgColorEnabled_ = enabled;
}
void ShowCaretAndStopTwinkling();
bool IsTextEditableForStylus() override;
@ -1487,6 +1520,11 @@ private:
void InitMouseEvent();
void HandleHoverEffect(MouseInfo& info, bool isHover);
void OnHover(bool isHover);
void UpdateHoverStyle(bool isHover);
void UpdatePressStyle(bool isPressed);
void PlayAnimationHoverAndPress(const Color& color);
void UpdateTextFieldBgColor(const Color& color);
void InitTextFieldThemeColors(const RefPtr<TextFieldTheme>& theme);
void ChangeMouseState(
const Offset location, const RefPtr<PipelineContext>& pipeline, int32_t frameId, bool isByPass = false);
void HandleMouseEvent(MouseInfo& info);
@ -1588,6 +1626,7 @@ private:
void PaintTextRect();
void GetIconPaintRect(const RefPtr<TextInputResponseArea>& responseArea, RoundRect& paintRect);
void GetInnerFocusPaintRect(RoundRect& paintRect);
void GetTextInputFocusPaintRect(RoundRect& paintRect);
void PaintResponseAreaRect();
void PaintCancelRect();
void PaintUnitRect();
@ -1675,6 +1714,7 @@ private:
RectF frameRect_;
RectF textRect_;
float textParagraphIndent_ = 0.0;
RefPtr<Paragraph> paragraph_;
RefPtr<Paragraph> errorParagraph_;
RefPtr<Paragraph> dragParagraph_;
@ -1841,6 +1881,17 @@ private:
bool textAreaBlurOnSubmit_ = false;
bool isDetachFromMainTree_ = false;
bool haveTextFadeoutCapacity_ = false;
bool isFocusTextColorSet_ = false;
bool isFocusBGColorSet_ = false;
bool isFocusPlaceholderColorSet_ = false;
Color defaultThemeBgColor_ = Color::TRANSPARENT;
Color focusThemeBgColor_ = Color::TRANSPARENT;
Color hoverThemeBgColor_ = Color::TRANSPARENT;
Color pressThemeBgColor_ = Color::TRANSPARENT;
bool hoverAndPressBgColorEnabled_ = false;
std::function<void(bool)> isFocusActiveUpdateEvent_;
Dimension previewUnderlineWidth_ = 2.0_vp;
bool hasSupportedPreviewText_ = true;
bool hasPreviewText_ = false;