From 1797f308385a4ee16b24e68a80dc5854b4d732e6 Mon Sep 17 00:00:00 2001 From: xiexiyun Date: Mon, 19 Dec 2022 11:59:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E6=A1=86=E6=9E=B6=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E6=A1=86=E6=89=8B=E6=9F=84=E7=A7=BB=E5=8A=A8=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xiexiyun --- .../text_field/render_text_field.cpp | 6 +- .../text_field_layout_algorithm.cpp | 44 ++--- .../text_field/text_field_paint_method.cpp | 9 +- .../pattern/text_field/text_field_pattern.cpp | 166 ++++++++++++------ .../pattern/text_field/text_field_pattern.h | 23 ++- 5 files changed, 167 insertions(+), 81 deletions(-) diff --git a/frameworks/core/components/text_field/render_text_field.cpp b/frameworks/core/components/text_field/render_text_field.cpp index fd0d6fd4649..9c478281320 100644 --- a/frameworks/core/components/text_field/render_text_field.cpp +++ b/frameworks/core/components/text_field/render_text_field.cpp @@ -132,6 +132,8 @@ void GetKeyboardFilter(TextInputType keyboard, std::string& keyboardFilterValue) void RenderTextField::UpdateConfiguration() { MiscServices::Configuration configuration; + LOGI("UpdateConfiguration: Enter key type %{public}d", static_cast(action_)); + LOGI("UpdateConfiguration: Enter keyboard type %{public}d", static_cast(keyboard_)); configuration.SetEnterKeyType(static_cast((int32_t)action_)); configuration.SetTextInputType(static_cast((int32_t)keyboard_)); MiscServices::InputMethodController::GetInstance()->OnConfigurationChange(configuration); @@ -353,9 +355,6 @@ void RenderTextField::Update(const RefPtr& component) if (textField->IsSetFocusOnTouch()) { isFocusOnTouch_ = textField->IsFocusOnTouch(); } -#if defined(ENABLE_STANDARD_INPUT) - UpdateConfiguration(); -#endif SetCallback(textField); UpdateFocusStyles(); UpdateIcon(textField); @@ -1077,6 +1076,7 @@ bool RenderTextField::RequestKeyboard(bool isFocusViewChanged, bool needStartTwi if (softKeyboardEnabled_) { LOGI("Request open soft keyboard"); #if defined(ENABLE_STANDARD_INPUT) + UpdateConfiguration(); if (textChangeListener_ == nullptr) { textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this), context_); } diff --git a/frameworks/core/components_ng/pattern/text_field/text_field_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/text_field/text_field_layout_algorithm.cpp index 3f83404aba5..01426dd8308 100644 --- a/frameworks/core/components_ng/pattern/text_field/text_field_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/text_field/text_field_layout_algorithm.cpp @@ -15,8 +15,6 @@ #include "core/components_ng/pattern/text_field/text_field_layout_algorithm.h" -#include -#include #include #include "base/geometry/axis.h" @@ -110,7 +108,7 @@ std::optional TextFieldLayoutAlgorithm::MeasureContent( if (textContent.empty()) { preferredHeight = pattern->PreferredLineHeight(); } - auto showPasswordIcon = textFieldLayoutProperty->GetShowPasswordIcon().value_or(false); + auto showPasswordIcon = textFieldLayoutProperty->GetShowPasswordIcon().value_or(true); // check password image size. if (!showPasswordIcon || !isPasswordType) { textRect_.SetSize(SizeF(static_cast(paragraph_->GetLongestLine()), preferredHeight)); @@ -153,23 +151,11 @@ void TextFieldLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) const auto& content = layoutWrapper->GetGeometryNode()->GetContent(); CHECK_NULL_VOID(content); auto contentSize = content->GetRect().GetSize(); - auto textRectOffsetX = pattern->GetPaddingLeft(); auto layoutProperty = DynamicCast(layoutWrapper->GetLayoutProperty()); CHECK_NULL_VOID(layoutProperty); auto context = layoutWrapper->GetHostNode()->GetContext(); CHECK_NULL_VOID(context); - switch (layoutProperty->GetTextAlignValue(TextAlign::START)) { - case TextAlign::START: - break; - case TextAlign::CENTER: - textRectOffsetX += contentSize.Width() / 2.0f - textRect_.Width() / 2.0f; - break; - case TextAlign::END: - textRectOffsetX += contentSize.Width() - textRect_.Width(); - break; - default: - break; - } + parentGlobalOffset_ = layoutWrapper->GetHostNode()->GetPaintRectOffset() - context->GetRootRect().GetOffset(); auto align = Alignment::CENTER; if (layoutWrapper->GetLayoutProperty()->GetPositionProperty()) { align = layoutWrapper->GetLayoutProperty()->GetPositionProperty()->GetAlignment().value_or(align); @@ -177,10 +163,28 @@ void TextFieldLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) // Update content position. auto contentOffset = Alignment::GetAlignPosition(size, contentSize, align); content->SetOffset(OffsetF(pattern->GetPaddingLeft(), contentOffset.GetY())); - // update text rect. - auto textOffset = Alignment::GetAlignPosition(contentSize, textRect_.GetSize(), Alignment::CENTER_LEFT); - // adjust text rect to the basic padding first - textRect_.SetOffset(OffsetF(textRectOffsetX, textOffset.GetY())); + // if handler is moving, no need to adjust text rect in pattern + if (pattern->GetCaretUpdateType() == CaretUpdateType::HANDLE_MOVE || + pattern->GetCaretUpdateType() == CaretUpdateType::HANDLE_MOVE_DONE) { + textRect_ = pattern->GetTextRect(); + } else { + auto textOffset = Alignment::GetAlignPosition(contentSize, textRect_.GetSize(), Alignment::CENTER_LEFT); + // adjust text rect to the basic padding + auto textRectOffsetX = pattern->GetPaddingLeft(); + switch (layoutProperty->GetTextAlignValue(TextAlign::START)) { + case TextAlign::START: + break; + case TextAlign::CENTER: + textRectOffsetX += (contentSize.Width() - textRect_.Width()) * 0.5f; + break; + case TextAlign::END: + textRectOffsetX += contentSize.Width() - textRect_.Width(); + break; + default: + break; + } + textRect_.SetOffset(OffsetF(textRectOffsetX, textOffset.GetY())); + } // update image rect. if (!imageRect_.IsEmpty()) { auto imageOffset = Alignment::GetAlignPosition(size, imageRect_.GetSize(), Alignment::CENTER_RIGHT); diff --git a/frameworks/core/components_ng/pattern/text_field/text_field_paint_method.cpp b/frameworks/core/components_ng/pattern/text_field/text_field_paint_method.cpp index f6aa4932b85..c6090fe9dd0 100644 --- a/frameworks/core/components_ng/pattern/text_field/text_field_paint_method.cpp +++ b/frameworks/core/components_ng/pattern/text_field/text_field_paint_method.cpp @@ -14,9 +14,6 @@ */ #include "core/components_ng/pattern/text_field/text_field_paint_method.h" -#include -#include - #include "foundation/graphic/graphic_2d/rosen/modules/2d_graphics/include/draw/path.h" #include "base/geometry/ng/offset_t.h" @@ -56,8 +53,10 @@ CanvasDrawFunction TextFieldPaintMethod::GetContentDrawFunction(PaintWrapper* pa contentOffset = paintWrapper->GetContentOffset(), passwordIconCanvasImage](RSCanvas& canvas) { CHECK_NULL_VOID_NOLOG(textFieldPattern); - RSRect clipInnerRect(offset.GetX(), contentOffset.GetY(), textFieldPattern->GetFrameRect().Width(), - contentOffset.GetY() + contentSize.Height()); + auto frameRect = textFieldPattern->GetFrameRect(); + RSRect clipInnerRect(offset.GetX(), 0.0f, + textFieldPattern->NeedShowPasswordIcon() ? frameRect.Width() : contentSize.Width() + contentOffset.GetX(), + frameRect.Height()); canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT); if (paragraph) { paragraph->Paint(&canvas, textFieldPattern->GetTextRect().GetX(), offset.GetY()); diff --git a/frameworks/core/components_ng/pattern/text_field/text_field_pattern.cpp b/frameworks/core/components_ng/pattern/text_field/text_field_pattern.cpp index 81be6d649ca..c8cb9f3e915 100644 --- a/frameworks/core/components_ng/pattern/text_field/text_field_pattern.cpp +++ b/frameworks/core/components_ng/pattern/text_field/text_field_pattern.cpp @@ -182,7 +182,8 @@ TextFieldPattern::~TextFieldPattern() void TextFieldPattern::UpdateConfiguration() { MiscServices::Configuration configuration; - LOGI("Enter key type %{public}d", (int32_t)GetTextInputActionValue(TextInputAction::DONE)); + LOGI("UpdateConfiguration: Enter key type %{public}d", (int32_t)GetTextInputActionValue(TextInputAction::DONE)); + LOGI("UpdateConfiguration: Enter keyboard type %{public}d", static_cast(keyboard_)); configuration.SetEnterKeyType( static_cast(static_cast(GetTextInputActionValue(TextInputAction::DONE)))); configuration.SetTextInputType(static_cast(static_cast(keyboard_))); @@ -213,6 +214,7 @@ bool TextFieldPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dir AdjustTextRectOffsetX(); AdjustTextAreaOffsetY(); UpdateSelectionOffset(); + SetHandlerOnMoveDone(); return true; } @@ -228,27 +230,12 @@ bool TextFieldPattern::UpdateCaretPosition() return true; } } - if (needCloseOverlay_ && SelectOverlayIsOn()) { - CloseSelectOverlay(); - needCloseOverlay_ = true; - } // text input has higher priority than events such as mouse press if (caretUpdateType_ == CaretUpdateType::INPUT) { UpdateCaretPositionByTextEdit(); StartTwinkling(); } else if (caretUpdateType_ == CaretUpdateType::PRESSED || caretUpdateType_ == CaretUpdateType::LONG_PRESSED) { - // caret offset updated by gesture will not cause textRect to change offset - UpdateCaretPositionByPressOffset(); - if (caretUpdateType_ == CaretUpdateType::PRESSED) { - StartTwinkling(); - CloseSelectOverlay(); - } - // in long press case, we have caret and one handle at pressed location and another handle at -1 or +1 position - if (caretUpdateType_ == CaretUpdateType::LONG_PRESSED) { - ProcessOverlay(); - UpdateSelectionOffset(); - } - return true; + UpdateCaretByPressOrLongPress(); } else if (caretUpdateType_ == CaretUpdateType::EVENT || caretUpdateType_ == CaretUpdateType::DEL) { UpdateCaretOffsetByEvent(); StartTwinkling(); @@ -259,12 +246,56 @@ bool TextFieldPattern::UpdateCaretPosition() caretRect_.SetLeft(textRect_.GetX() + textRect_.Width()); } return true; - } else if (caretUpdateType_ == CaretUpdateType::HANDLER_MOVE) { - return true; + } else if (caretUpdateType_ == CaretUpdateType::HANDLE_MOVE) { + StartTwinkling(); } return false; } +void TextFieldPattern::CreateSingleHandle() +{ + RectF firstHandle; + OffsetF firstHandleOffset( + caretRect_.GetX() + parentGlobalOffset_.GetX(), contentRect_.GetY() + parentGlobalOffset_.GetY()); + SizeF handlePaintSize = { SelectHandleInfo::GetDefaultLineWidth().ConvertToPx(), contentRect_.Height() }; + firstHandle.SetOffset(firstHandleOffset); + firstHandle.SetSize(handlePaintSize); + ShowSelectOverlay(firstHandle, std::nullopt); + selectionMode_ = SelectionMode::NONE; + StopTwinkling(); +} + +bool TextFieldPattern::UpdateCaretByPressOrLongPress() +{ + if (!SelectOverlayIsOn() && caretUpdateType_ != CaretUpdateType::LONG_PRESSED) { + isSingleHandle_ = true; + CreateSingleHandle(); + return true; + } + // caret offset updated by gesture will not cause textRect to change offset + UpdateCaretPositionByPressOffset(); + if (caretUpdateType_ == CaretUpdateType::PRESSED) { + StartTwinkling(); + CloseSelectOverlay(); + } + // in long press case, we have caret and one handle at pressed location and another handle at -1 or +1 position + if (caretUpdateType_ == CaretUpdateType::LONG_PRESSED) { + ProcessOverlay(); + UpdateSelectionOffset(); + } + return true; +} + +bool TextFieldPattern::CaretPositionCloseToTouchPosition() +{ + auto fontSize = GetTextOrPlaceHolderFontSize(); + auto xInRange = GreatOrEqual(lastTouchOffset_.GetX(), caretRect_.GetX() - fontSize) && + LessOrEqual(lastTouchOffset_.GetX(), caretRect_.GetX() + fontSize); + auto yInRange = GreatOrEqual(lastTouchOffset_.GetY(), caretRect_.GetY() + contentRect_.GetY()) && + LessOrEqual(lastTouchOffset_.GetY(), caretRect_.GetY() + contentRect_.GetY() + fontSize); + return xInRange && yInRange; +} + bool TextFieldPattern::IsTextArea() { auto layoutProperty = GetHost()->GetLayoutProperty(); @@ -365,8 +396,8 @@ void TextFieldPattern::UpdateSelectionOffset() std::optional secondHandleOption; if (SelectOverlayIsOn()) { SizeF handlePaintSize = { SelectHandleInfo::GetDefaultLineWidth().ConvertToPx(), contentRect_.Height() }; - if (GreatOrEqual(textSelector_.selectionBaseOffset.GetX(), textRect_.GetX()) && - LessOrEqual(textSelector_.selectionBaseOffset.GetX(), textRect_.GetX() + textRect_.Width())) { + if (GreatOrEqual(textSelector_.selectionBaseOffset.GetX(), contentRect_.GetX()) && + LessOrEqual(textSelector_.selectionBaseOffset.GetX(), contentRect_.GetX() + contentRect_.Width())) { OffsetF firstHandleOffset(textSelector_.selectionBaseOffset.GetX() + parentGlobalOffset_.GetX(), contentRect_.GetY() + parentGlobalOffset_.GetY()); RectF firstHandle; @@ -374,8 +405,9 @@ void TextFieldPattern::UpdateSelectionOffset() firstHandle.SetSize(handlePaintSize); firstHandleOption = firstHandle; } - if (GreatOrEqual(textSelector_.selectionDestinationOffset.GetX(), textRect_.GetX()) && - LessOrEqual(textSelector_.selectionDestinationOffset.GetX(), textRect_.GetX() + textRect_.Width())) { + if (GreatOrEqual(textSelector_.selectionDestinationOffset.GetX(), contentRect_.GetX()) && + LessOrEqual( + textSelector_.selectionDestinationOffset.GetX(), contentRect_.GetX() + contentRect_.Width())) { OffsetF secondHandleOffset(textSelector_.selectionDestinationOffset.GetX() + parentGlobalOffset_.GetX(), contentRect_.GetY() + parentGlobalOffset_.GetY()); RectF secondHandle; @@ -616,6 +648,7 @@ void TextFieldPattern::HandleFocusEvent() { LOGI("TextField %{public}d on focus", GetHost()->GetId()); caretUpdateType_ = CaretUpdateType::EVENT; + CloseSelectOverlay(); auto layoutProperty = GetLayoutProperty(); CHECK_NULL_VOID(layoutProperty); GetHost()->MarkDirtyNode(layoutProperty->GetMaxLinesValue(Infinity()) <= 1 ? PROPERTY_UPDATE_MEASURE_SELF @@ -668,6 +701,7 @@ void TextFieldPattern::HandleBlurEvent() bool TextFieldPattern::OnKeyEvent(const KeyEvent& event) { caretUpdateType_ = CaretUpdateType::EVENT; + CloseSelectOverlay(); return HandleKeyEvent(event); } @@ -911,6 +945,7 @@ void TextFieldPattern::HandleOnCut() SetEditingValueToProperty(textEditingValue_.text); selectionMode_ = SelectionMode::NONE; caretUpdateType_ = CaretUpdateType::EVENT; + CloseSelectOverlay(); operationRecords_.emplace_back(textEditingValue_); auto host = GetHost(); @@ -964,6 +999,9 @@ void TextFieldPattern::FireEventHubOnChange(const std::string& text) void TextFieldPattern::HandleTouchEvent(const TouchEventInfo& info) { + if (SelectOverlayIsOn()) { + return; + } auto touchType = info.GetTouches().front().GetTouchType(); if (touchType == TouchType::DOWN) { HandleTouchDown(info.GetTouches().front().GetLocalLocation()); @@ -1036,9 +1074,10 @@ void TextFieldPattern::HandleClickEvent(GestureEvent& info) lastTouchOffset_ = info.GetLocalLocation(); caretUpdateType_ = CaretUpdateType::PRESSED; selectionMode_ = SelectionMode::NONE; + CloseSelectOverlay(); auto layoutProperty = GetLayoutProperty(); if (lastTouchOffset_.GetX() > frameRect_.Width() - imageRect_.Width() - GetPaddingRight() && - layoutProperty->GetShowPasswordIcon().value_or(false) && + layoutProperty->GetShowPasswordIcon().value_or(true) && layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::VISIBLE_PASSWORD) { textObscured_ = !textObscured_; ProcessPasswordIcon(); @@ -1133,9 +1172,6 @@ void TextFieldPattern::OnModifyDone() CloseKeyboard(true); keyboard_ = layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED); } -#if defined(ENABLE_STANDARD_INPUT) - UpdateConfiguration(); -#endif InitClickEvent(); InitLongPressEvent(); InitFocusEvent(); @@ -1209,6 +1245,7 @@ void TextFieldPattern::HandleLongPress(GestureEvent& info) lastTouchOffset_ = info.GetLocalLocation(); caretUpdateType_ = CaretUpdateType::LONG_PRESSED; selectionMode_ = SelectionMode::SELECT; + isSingleHandle_ = false; LOGI("TextField %{public}d handle long press", GetHost()->GetId()); auto focusHub = GetHost()->GetOrCreateFocusHub(); if (!focusHub->RequestFocusImmediately()) { @@ -1320,6 +1357,11 @@ void TextFieldPattern::ShowSelectOverlay( pattern->HandleOnSelectAll(); pattern->SetNeedCloseOverlay(false); }; + auto host = pattern->GetHost(); + CHECK_NULL_VOID_NOLOG(host); + auto gesture = host->GetOrCreateGestureEventHub(); + gesture->RemoveTouchEvent(pattern->GetTouchListener()); + pattern->SetSelectOverlay(pipeline->GetSelectOverlayManager()->CreateAndShowSelectOverlay(selectInfo)); }; clipboard_->HasData(hasDataCallback); @@ -1332,7 +1374,12 @@ void TextFieldPattern::OnDetachFromFrameNode(FrameNode* node) void TextFieldPattern::CloseSelectOverlay() { + auto host = GetHost(); + CHECK_NULL_VOID_NOLOG(host); + auto gesture = host->GetOrCreateGestureEventHub(); + gesture->AddTouchEvent(GetTouchListener()); CHECK_NULL_VOID_NOLOG(selectOverlayProxy_); + LOGI("Close select overlay"); selectOverlayProxy_->Close(); } @@ -1348,12 +1395,13 @@ bool TextFieldPattern::SelectOverlayIsOn() void TextFieldPattern::OnHandleMove(const RectF& handleRect, bool isFirstHandle) { CHECK_NULL_VOID_NOLOG(SelectOverlayIsOn()); - int32_t position; + int32_t position = 0; auto localOffsetX = handleRect.GetOffset().GetX() - parentGlobalOffset_.GetX(); if (localOffsetX < contentRect_.GetX()) { - position = 0; + position = std::max(static_cast(textEditingValue_.caretPosition - 1), 0); } else if (GreatOrEqual(localOffsetX, contentRect_.GetX() + contentRect_.Width())) { - position = static_cast(textEditingValue_.GetWideText().length()); + position = std::min(static_cast(textEditingValue_.caretPosition + 1), + static_cast(textEditingValue_.GetWideText().length())); } else { Offset offset(localOffsetX - textRect_.GetX(), 0.0f); position = ConvertTouchOffsetToCaretPosition(offset); @@ -1361,15 +1409,21 @@ void TextFieldPattern::OnHandleMove(const RectF& handleRect, bool isFirstHandle) textEditingValue_.CursorMoveToPosition(position); OffsetF offsetToParagraphBeginning = CalcCursorOffsetByPosition(position); caretRect_.SetOffset(offsetToParagraphBeginning + OffsetF(textRect_.GetOffset().GetX(), 0.0f)); - selectionMode_ = SelectionMode::SELECT; - caretUpdateType_ = CaretUpdateType::HANDLER_MOVE; + selectionMode_ = isSingleHandle_ ? SelectionMode::NONE : SelectionMode::SELECT; + caretUpdateType_ = CaretUpdateType::HANDLE_MOVE; UpdateTextSelectorByHandleMove(isFirstHandle, position, offsetToParagraphBeginning); - GetHost()->MarkDirtyNode(PROPERTY_UPDATE_RENDER); + GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); } void TextFieldPattern::UpdateTextSelectorByHandleMove( bool isMovingBase, int32_t position, OffsetF& offsetToParagraphBeginning) { + if (isSingleHandle_) { + UpdateSelection(position); + textSelector_.selectionBaseOffset = offsetToParagraphBeginning + OffsetF(textRect_.GetOffset().GetX(), 0.0f); + textSelector_.selectionDestinationOffset = textSelector_.selectionBaseOffset; + return; + } if (isMovingBase) { textSelector_.baseOffset = position; textSelector_.selectionBaseOffset = offsetToParagraphBeginning + OffsetF(textRect_.GetOffset().GetX(), 0.0f); @@ -1382,30 +1436,28 @@ void TextFieldPattern::UpdateTextSelectorByHandleMove( void TextFieldPattern::OnHandleMoveDone(const RectF& handleRect, bool isFirstHandle) { CHECK_NULL_VOID_NOLOG(SelectOverlayIsOn()); - auto offsetXToFrameRect = handleRect.GetOffset().GetX() - frameRect_.GetX(); - int32_t position = 0; - if (LessOrEqual(offsetXToFrameRect, 0.0f)) { - position = 0; - } else if (GreatNotEqual(offsetXToFrameRect, frameRect_.GetX() + frameRect_.Width())) { - position = static_cast(textEditingValue_.GetWideText().length()); - } else { - Offset offset(std::max(offsetXToFrameRect, 0.0f), 0.0f); - position = ConvertTouchOffsetToCaretPosition(offset); + isFirstHandle_ = isFirstHandle; + caretUpdateType_ = CaretUpdateType::HANDLE_MOVE_DONE; + GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); +} + +void TextFieldPattern::SetHandlerOnMoveDone() +{ + if (caretUpdateType_ != CaretUpdateType::HANDLE_MOVE_DONE) { + return; } - textEditingValue_.CursorMoveToPosition(position); + SelectHandleInfo info; auto newHandleOffset = - parentGlobalOffset_ + OffsetF(isFirstHandle ? textSelector_.selectionBaseOffset.GetX() - : textSelector_.selectionDestinationOffset.GetX(), + parentGlobalOffset_ + OffsetF(isFirstHandle_ ? textSelector_.selectionBaseOffset.GetX() + : textSelector_.selectionDestinationOffset.GetX(), contentRect_.GetY()); SizeF handlePaintSize = { SelectHandleInfo::GetDefaultLineWidth().ConvertToPx(), contentRect_.Height() }; RectF newHandle; newHandle.SetOffset(newHandleOffset); newHandle.SetSize(handlePaintSize); - SelectHandleInfo info; info.paintRect = newHandle; - selectionMode_ = SelectionMode::SELECT; - caretUpdateType_ = CaretUpdateType::HANDLER_MOVE; - if (isFirstHandle) { + selectionMode_ = isSingleHandle_ ? SelectionMode::NONE : SelectionMode::SELECT; + if (isFirstHandle_) { selectOverlayProxy_->UpdateFirstSelectHandleInfo(info); return; } @@ -1466,6 +1518,7 @@ void TextFieldPattern::OnHover(bool isHover) void TextFieldPattern::HandleMouseEvent(const MouseInfo& info) { auto focusHub = GetHost()->GetOrCreateFocusHub(); + CloseSelectOverlay(); if (info.GetAction() == MouseAction::PRESS) { if (!focusHub->IsFocusable()) { return; @@ -1531,6 +1584,7 @@ bool TextFieldPattern::RequestKeyboard(bool isFocusViewChanged, bool needStartTw if (needShowSoftKeyboard) { LOGI("Start to request keyboard"); #if defined(ENABLE_STANDARD_INPUT) + UpdateConfiguration(); if (textChangeListener_ == nullptr) { textChangeListener_ = new OnTextChangedListenerImpl(WeakClaim(this)); } @@ -1765,6 +1819,7 @@ void TextFieldPattern::InsertValue(const std::string& insertValue) operationRecords_.emplace_back(textEditingValue_); caretUpdateType_ = CaretUpdateType::INPUT; selectionMode_ = SelectionMode::NONE; + CloseSelectOverlay(); auto host = GetHost(); CHECK_NULL_VOID(host); // If the parent node is a Search, the Search callback is executed. @@ -1955,6 +2010,7 @@ void TextFieldPattern::Delete(int32_t start, int32_t end) FireEventHubOnChange(GetEditingValue().text); selectionMode_ = SelectionMode::NONE; caretUpdateType_ = CaretUpdateType::INPUT; + CloseSelectOverlay(); operationRecords_.emplace_back(textEditingValue_); auto layoutProperty = GetHost()->GetLayoutProperty(); CHECK_NULL_VOID(layoutProperty); @@ -2019,13 +2075,18 @@ void TextFieldPattern::OnAreaChangedInner() auto parentGlobalOffset = host->GetPaintRectOffset() - context->GetRootRect().GetOffset(); if (parentGlobalOffset != parentGlobalOffset_) { parentGlobalOffset_ = parentGlobalOffset; - ProcessOverlay(); - selectionMode_ = SelectionMode::SELECT; textSelector_.selectionBaseOffset.SetX( CalcCursorOffsetByPosition(textSelector_.GetStart()).GetX() + textRect_.GetX()); textSelector_.selectionDestinationOffset.SetX( CalcCursorOffsetByPosition(textSelector_.GetEnd()).GetX() + textRect_.GetX()); UpdateSelection(textSelector_.GetStart(), textSelector_.GetEnd()); + if (isSingleHandle_) { + CloseSelectOverlay(); + CreateSingleHandle(); + return; + } + ProcessOverlay(); + selectionMode_ = SelectionMode::SELECT; } } @@ -2061,6 +2122,7 @@ void TextFieldPattern::DeleteForward(int32_t length) FireEventHubOnChange(GetEditingValue().text); selectionMode_ = SelectionMode::NONE; caretUpdateType_ = CaretUpdateType::DEL; + CloseSelectOverlay(); operationRecords_.emplace_back(textEditingValue_); auto layoutProperty = GetHost()->GetLayoutProperty(); CHECK_NULL_VOID(layoutProperty); @@ -2085,6 +2147,7 @@ void TextFieldPattern::DeleteBackward(int32_t length) FireEventHubOnChange(GetEditingValue().text); selectionMode_ = SelectionMode::NONE; caretUpdateType_ = CaretUpdateType::INPUT; + CloseSelectOverlay(); operationRecords_.emplace_back(textEditingValue_); auto layoutProperty = GetHost()->GetLayoutProperty(); CHECK_NULL_VOID(layoutProperty); @@ -2178,6 +2241,7 @@ void TextFieldPattern::SetCaretPosition(int32_t position) textEditingValue_.caretPosition = std::clamp(position, 0, static_cast(textEditingValue_.text.length())); selectionMode_ = SelectionMode::NONE; caretUpdateType_ = CaretUpdateType::EVENT; + CloseSelectOverlay(); GetHost()->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); } diff --git a/frameworks/core/components_ng/pattern/text_field/text_field_pattern.h b/frameworks/core/components_ng/pattern/text_field/text_field_pattern.h index ac05100d43b..deac378749a 100644 --- a/frameworks/core/components_ng/pattern/text_field/text_field_pattern.h +++ b/frameworks/core/components_ng/pattern/text_field/text_field_pattern.h @@ -60,7 +60,7 @@ constexpr Dimension CURSOR_PADDING = 2.0_vp; enum class SelectionMode { SELECT, SELECT_ALL, NONE }; -enum class CaretUpdateType { PRESSED, LONG_PRESSED, DEL, EVENT, HANDLER_MOVE, INPUT, NONE }; +enum class CaretUpdateType { PRESSED, LONG_PRESSED, DEL, EVENT, HANDLE_MOVE, HANDLE_MOVE_DONE, INPUT, NONE }; class TextFieldPattern : public Pattern, public ValueChangeObserver { DECLARE_ACE_TYPE(TextFieldPattern, Pattern, ValueChangeObserver); @@ -326,7 +326,7 @@ public: { return showPasswordImageLoadingCtx_; } - + void SearchRequestKeyboard(); const RefPtr& GetShowPasswordIconCanvasImage() const @@ -361,6 +361,19 @@ public: return imageRect_; } + const RefPtr& GetTouchListener() + { + return touchListener_; + } + + bool NeedShowPasswordIcon() + { + auto layoutProperty = GetLayoutProperty(); + CHECK_NULL_RETURN_NOLOG(layoutProperty, false); + return layoutProperty->GetTextInputTypeValue(TextInputType::UNSPECIFIED) == TextInputType::VISIBLE_PASSWORD && + layoutProperty->GetShowPasswordIconValue(true); + } + const ImagePaintConfig& GetPasswordIconPaintConfig() { return passwordIconPaintConfig_; @@ -381,6 +394,8 @@ private: void InitTouchEvent(); void InitLongPressEvent(); void InitClickEvent(); + bool CaretPositionCloseToTouchPosition(); + void CreateSingleHandle(); void AddScrollEvent(); void OnTextAreaScroll(float dy); @@ -395,7 +410,9 @@ private: void ProcessOverlay(); void OnHandleMove(const RectF& handleRect, bool isFirstHandle); void OnHandleMoveDone(const RectF& handleRect, bool isFirstHandle); + void SetHandlerOnMoveDone(); void OnDetachFromFrameNode(FrameNode* node) override; + bool UpdateCaretByPressOrLongPress(); void UpdateTextSelectorByHandleMove(bool isMovingBase, int32_t position, OffsetF& offsetToParagraphBeginning); void HandleSelectionUp(); @@ -502,6 +519,8 @@ private: Offset lastTouchOffset_; PaddingPropertyF utilPadding_; + bool isSingleHandle_ = false; + bool isFirstHandle_ = false; float baselineOffset_ = 0.0f; RectF caretRect_; bool cursorVisible_ = false; -- Gitee