!47305 RichEditor新避让功能优化

Merge pull request !47305 from 姚明/REBug
This commit is contained in:
openharmony_ci 2024-10-31 08:09:05 +00:00 committed by Gitee
commit 60f8957906
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 101 additions and 63 deletions

View File

@ -42,8 +42,9 @@ bool RichEditorBaseController::SetCaretOffset(int32_t caretPosition)
{
auto richEditorPattern = pattern_.Upgrade();
CHECK_NULL_RETURN(richEditorPattern, false);
richEditorPattern->TriggerAvoidOnCaretChange();
return richEditorPattern->SetCaretOffset(caretPosition);
auto result = richEditorPattern->SetCaretOffset(caretPosition);
richEditorPattern->ForceTriggerAvoidOnCaretChange(true);
return result;
}
void RichEditorBaseController::SetTypingStyle(std::optional<struct UpdateSpanStyle> typingStyle,
@ -88,7 +89,7 @@ void RichEditorBaseController::SetSelection(
auto richEditorPattern = pattern_.Upgrade();
CHECK_NULL_VOID(richEditorPattern);
richEditorPattern->SetSelection(selectionStart, selectionEnd, options, isForward);
richEditorPattern->TriggerAvoidOnCaretChange();
richEditorPattern->ForceTriggerAvoidOnCaretChange();
}
const PreviewTextInfo RichEditorBaseController::GetPreviewTextInfo() const

View File

@ -65,7 +65,7 @@ void RichEditorController::UpdateSpanStyle(
}
richEditorPattern->SetUpdateSpanStyle(updateSpanStyle_);
richEditorPattern->UpdateSpanStyle(start, end, textStyle, imageStyle);
richEditorPattern->TriggerAvoidOnCaretChange();
richEditorPattern->ForceTriggerAvoidOnCaretChange();
}
void RichEditorController::SetUpdateSpanStyle(struct UpdateSpanStyle updateSpanStyle)
@ -110,7 +110,7 @@ void RichEditorController::UpdateParagraphStyle(int32_t start, int32_t end, cons
auto richEditorPattern = pattern_.Upgrade();
CHECK_NULL_VOID(richEditorPattern);
richEditorPattern->UpdateParagraphStyle(start, end, style);
richEditorPattern->TriggerAvoidOnCaretChange();
richEditorPattern->ForceTriggerAvoidOnCaretChange();
}
std::vector<ParagraphInfo> RichEditorController::GetParagraphsInfo(int32_t start, int32_t end)
{

View File

@ -86,7 +86,16 @@ void RichEditorPaintMethod::SetCaretOffsetAndHeight(PaintWrapper* paintWrapper)
CHECK_NULL_VOID(overlayMod);
CHECK_NULL_VOID(!richEditorPattern->IsMoveCaretAnywhere()); // Avoid to reset caret offset
auto [caretOffset, caretHeight] = richEditorPattern->CalculateCaretOffsetAndHeight();
auto lastOffset = overlayMod->GetCaretOffset();
auto lastCaretY = lastOffset.GetY() + overlayMod->GetCaretHeight() - richEditorPattern->GetLastTextRect().GetY();
auto curCaretY = caretOffset.GetY() + caretHeight - richEditorPattern->GetTextRect().GetY();
overlayMod->SetCaretOffsetAndHeight(caretOffset, caretHeight);
if (richEditorPattern->IsTriggerAvoidOnCaretAvoidMode() || !NearEqual(lastCaretY, curCaretY) ||
!NearEqual(lastOffset.GetX(), caretOffset.GetX())) {
richEditorPattern->NotifyCaretChange();
richEditorPattern->ResetTriggerAvoidFlagOnCaretChange();
}
richEditorPattern->ChangeLastRichTextRect();
}
void RichEditorPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)

View File

@ -158,6 +158,7 @@ void RichEditorPattern::SetStyledString(const RefPtr<SpanString>& value)
styledString_->AddCustomSpan();
styledString_->SetFramNode(WeakClaim(host.GetRawPtr()));
host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
ForceTriggerAvoidOnCaretChange();
}
void RichEditorPattern::UpdateSpanItems(const std::list<RefPtr<NG::SpanItem>>& spanItems)
@ -466,7 +467,7 @@ void RichEditorPattern::AfterStyledStringChange(int32_t start, int32_t length, c
changeValue.SetRangeAfter({ changeStart, stringEnd });
eventHub->FireOnStyledStringDidChange(changeValue);
}
TriggerAvoidOnCaretChange();
ForceTriggerAvoidOnCaretChange();
}
void RichEditorPattern::OnModifyDone()
@ -517,7 +518,6 @@ void RichEditorPattern::OnModifyDone()
enabled_ = enabledCache;
host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
}
TriggerAvoidOnCaretChangeAfterLayoutTask();
}
void RichEditorPattern::HandleEnabled()
@ -594,7 +594,6 @@ void RichEditorPattern::ClearOnFocusTextField()
bool RichEditorPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
{
CHECK_NULL_RETURN(!config.skipMeasure && !dirty->SkipMeasureContent(), false);
auto originHeight = frameRect_.Height();
frameRect_ = dirty->GetGeometryNode()->GetFrameRect();
auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
@ -614,7 +613,7 @@ bool RichEditorPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& di
if (!isRichEditorInit_) {
FireOnReady();
}
MoveCaretOnLayoutSwap(LessNotEqual(originHeight, frameRect_.Height()));
MoveCaretOnLayoutSwap();
HandleTasksOnLayoutSwap();
HandleSelectOverlayOnLayoutSwap();
if (!isModifyingContent_) {
@ -671,10 +670,15 @@ void RichEditorPattern::SupplementIdealSizeWidth(const RefPtr<FrameNode>& frameN
}
}
void RichEditorPattern::MoveCaretOnLayoutSwap(bool isReduceSize)
void RichEditorPattern::MoveCaretOnLayoutSwap()
{
MoveCaretAfterTextChange();
bool needScroll = (needMoveCaretToContentRect_ || isEditing_) && !isReduceSize;
auto context = GetContext();
bool isResize = false;
if (context) {
isResize = context->GetEnableKeyBoardAvoidMode() == KeyBoardAvoidMode::RESIZE;
}
bool needScroll = (needMoveCaretToContentRect_ || isEditing_) && !isResize;
if (needScroll) {
MoveCaretToContentRect();
needMoveCaretToContentRect_ = false;
@ -798,7 +802,6 @@ RichEditorPattern::OneStepDragParam::OneStepDragParam(const std::function<void()
menuParam.onDisappear = selectMenuParam.onDisappear;
menuParam.previewAnimationOptions.scaleFrom = 1.0f;
menuParam.previewBorderRadius = BorderRadiusProperty(Dimension(0, DimensionUnit::VP));
menuParam.backgroundColor = Color::TRANSPARENT;
menuParam.backgroundBlurStyle = static_cast<int>(BlurStyle::NO_MATERIAL);
}
@ -1055,7 +1058,6 @@ int32_t RichEditorPattern::AddPlaceholderSpan(const RefPtr<UINode>& customNode,
placeholderPipelineContext->SetDoKeyboardAvoidAnimate(false);
}
SetNeedMoveCaretToContentRect();
TriggerAvoidOnCaretChange();
placeholderSpanNode->MarkModifyDone();
placeholderSpanNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
host->MarkModifyDone();
@ -1286,7 +1288,7 @@ void RichEditorPattern::AfterContentChange(RichEditorChangeValue& changeValue)
if (eventHub && eventHub->HasOnDidChange()) {
eventHub->FireOnDidChange(changeValue);
}
TriggerAvoidOnCaretChange();
ForceTriggerAvoidOnCaretChange();
}
void RichEditorPattern::SpanNodeFission(RefPtr<SpanNode>& spanNode)
@ -2700,7 +2702,7 @@ void RichEditorPattern::HandleClickEvent(GestureEvent& info)
HandleDoubleClickEvent(info);
} else {
HandleSingleClickEvent(info);
TriggerAvoidOnCaretChange();
NotifyCaretChange();
}
}
@ -3174,11 +3176,9 @@ void RichEditorPattern::HandleFocusEvent()
isFontScaleChanged = !NearEqual(lastFontScale_, currentFontScale);
lastFontScale_ = currentFontScale;
}
if (isCaretInContentArea_ && isFontScaleChanged) {
auto host = GetHost();
if (host) {
host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
}
auto host = GetHost();
if (host) {
host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
}
if (!usingMouseRightButton_ && !isLongPress_ && !isDragging_ && !dataDetectorAdapter_->hasClickedMenuOption_) {
auto windowMode = GetWindowMode();
@ -3355,6 +3355,11 @@ std::pair<OffsetF, float> RichEditorPattern::CalculateEmptyValueCaretRect()
return std::make_pair(offset, caretHeight);
}
void RichEditorPattern::NotifyCaretChange()
{
IF_TRUE(!IsSelected(), TriggerAvoidOnCaretChange());
}
TextAlign RichEditorPattern::GetTextAlignByDirection()
{
auto layoutProperty = GetLayoutProperty<TextLayoutProperty>();
@ -3448,6 +3453,7 @@ void RichEditorPattern::HandleDoubleClickOrLongPress(GestureEvent& info)
return;
}
HandleDoubleClickOrLongPress(info, host);
ForceTriggerAvoidOnCaretChange(true);
}
Offset RichEditorPattern::ConvertGlobalToLocalOffset(const Offset& globalOffset)
@ -6690,7 +6696,7 @@ void RichEditorPattern::HandleTouchUpAfterLongPress()
CalculateHandleOffsetAndShowOverlay();
selectOverlay_->ProcessOverlay({ .animation = true });
FireOnSelectionChange(selectStart, selectEnd);
IF_TRUE(IsSingleHandle(), TriggerAvoidOnCaretChange());
IF_TRUE(IsSingleHandle(), ForceTriggerAvoidOnCaretChange());
}
void RichEditorPattern::HandleTouchMove(const Offset& offset)
@ -7103,9 +7109,8 @@ void RichEditorPattern::TriggerAvoidOnCaretChange()
if (!safeAreaManager || NearZero(safeAreaManager->GetKeyboardInset().Length(), 0)) {
return;
}
textFieldManager->SetHeight(GetCaretRect().Height());
textFieldManager->TriggerAvoidOnCaretChange();
auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight();
SetLastCaretPos(caretPos);
}
void RichEditorPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
@ -7136,11 +7141,6 @@ void RichEditorPattern::OnWindowSizeChanged(int32_t width, int32_t height, Windo
TaskExecutor::TaskType::UI, "ArkUIRichEditorOnWindowSizeChangedRotation");
}
void RichEditorPattern::OnFontScaleConfigurationUpdate()
{
TriggerAvoidOnCaretChangeAfterLayoutTask();
}
void RichEditorPattern::CopySelectionMenuParams(SelectOverlayInfo& selectInfo, TextResponseType responseType)
{
auto selectType = selectedType_.value_or(TextSpanType::NONE);
@ -7264,26 +7264,6 @@ void RichEditorPattern::EncodeTlvDataByResultObject(const ResultObject& result,
spanString->EncodeTlv(tlvData);
}
void RichEditorPattern::TriggerAvoidOnCaretChangeAfterLayoutTask()
{
auto context = GetContext();
CHECK_NULL_VOID(context);
CHECK_NULL_VOID(context->UsingCaretAvoidMode());
auto textFieldManager = DynamicCast<TextFieldManagerNG>(context->GetTextFieldManager());
CHECK_NULL_VOID(textFieldManager);
context->AddAfterLayoutTask([weak = WeakClaim(this), manager = WeakPtr<TextFieldManagerNG>(textFieldManager)] {
auto textField = weak.Upgrade();
CHECK_NULL_VOID(textField);
auto textFieldManager = manager.Upgrade();
CHECK_NULL_VOID(textFieldManager);
auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight();
if (caretPos != textField->GetLastCaretPos()) {
TAG_LOGI(ACE_KEYBOARD, "Caret Position Change, Retrigger Avoid");
textField->TriggerAvoidOnCaretChange();
}
});
}
void RichEditorPattern::HandleOnCopy(bool isUsingExternalKeyboard)
{
CHECK_NULL_VOID(clipboard_);
@ -7828,7 +7808,6 @@ void RichEditorPattern::InitSelection(const Offset& pos)
TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "select rect is empty, select nothing");
textSelector_.Update(currentPosition, currentPosition);
}
TriggerAvoidOnCaretChangeAfterLayoutTask();
}
std::pair<int32_t, SelectType> RichEditorPattern::JudgeSelectType(const Offset& pos)
@ -10793,6 +10772,7 @@ void RichEditorPattern::UpdateSelectionByTouchMove(const Offset& touchOffset)
StartVibratorByIndexChange(start, textSelector_.GetTextStart());
}
HandleSelectionChange(start, end);
TriggerAvoidOnCaretChange();
host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
}

View File

@ -386,7 +386,7 @@ public:
void HandleSelectOverlayOnLayoutSwap();
void FireOnReady();
void SupplementIdealSizeWidth(const RefPtr<FrameNode>& frameNode);
void MoveCaretOnLayoutSwap(bool isReduceSize);
void MoveCaretOnLayoutSwap();
void UpdateEditingValue(const std::shared_ptr<TextEditingValue>& value, bool needFireChangeEvent = true) override;
void PerformAction(TextInputAction action, bool forceCloseKeyboard = true) override;
@ -566,6 +566,7 @@ public:
bool JudgeContentDraggable();
std::pair<OffsetF, float> CalculateCaretOffsetAndHeight();
std::pair<OffsetF, float> CalculateEmptyValueCaretRect();
void NotifyCaretChange();
TextAlign GetTextAlignByDirection();
void RemoveEmptySpan(std::set<int32_t, std::greater<int32_t>>& deleteSpanIndexs);
void RemoveEmptySpanItems();
@ -958,18 +959,41 @@ public:
void TriggerAvoidOnCaretChange();
void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) override;
void OnFontScaleConfigurationUpdate() override;
float GetLastCaretPos()
void ForceTriggerAvoidOnCaretChange(bool isMoveContent = false)
{
return lastCaretPos_;
auto pipeline = GetContext();
CHECK_NULL_VOID(pipeline && pipeline->UsingCaretAvoidMode());
IF_TRUE(isMoveContent, MoveCaretToContentRect());
isTriggerAvoidOnCaretAvoidMode_ = true;
}
void SetLastCaretPos(float lastCaretPos)
void ResetTriggerAvoidFlagOnCaretChange()
{
lastCaretPos_ = lastCaretPos;
isTriggerAvoidOnCaretAvoidMode_ = false;
}
void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) override;
bool IsTriggerAvoidOnCaretAvoidMode()
{
return isTriggerAvoidOnCaretAvoidMode_;
}
void SetAvoidFlagOnCaretAvoidMode(bool isTriggerAvoidOnCaretAvoidMode)
{
auto pipeline = GetContext();
CHECK_NULL_VOID(pipeline && pipeline->UsingCaretAvoidMode());
isTriggerAvoidOnCaretAvoidMode_ = isTriggerAvoidOnCaretAvoidMode;
}
void ChangeLastRichTextRect()
{
lastRichTextRect_ = richTextRect_;
}
const RectF& GetLastTextRect()
{
return lastRichTextRect_;
}
protected:
@ -1298,7 +1322,6 @@ private:
void ClearOnFocusTextField();
void ProcessResultObject(RefPtr<PasteDataMix> pasteData, const ResultObject& result);
void EncodeTlvDataByResultObject(const ResultObject& result, std::vector<uint8_t>& tlvData);
void TriggerAvoidOnCaretChangeAfterLayoutTask();
#if defined(ENABLE_STANDARD_INPUT)
sptr<OHOS::MiscServices::OnTextChangedListener> richEditTextChangeListener_;
@ -1419,7 +1442,8 @@ private:
bool isImageSelfResponseEvent_ = true;
std::optional<DisplayMode> barDisplayMode_ = std::nullopt;
uint32_t twinklingInterval_ = 0;
float lastCaretPos_ = 0.0f;
bool isTriggerAvoidOnCaretAvoidMode_ = false;
RectF lastRichTextRect_;
};
} // namespace OHOS::Ace::NG

View File

@ -154,7 +154,9 @@ void RichEditorSelectOverlay::OnHandleMove(const RectF& handleRect, bool isFirst
auto magnifierLocalOffset = OffsetF(x, y);
GetLocalPointWithTransform(magnifierLocalOffset); // do affine transformation
pattern->magnifierController_->SetLocalOffset(magnifierLocalOffset);
bool isChangeSecondHandle = isFirst ? pattern->textSelector_.StartGreaterDest() :
(!pattern->textSelector_.StartGreaterDest());
IF_TRUE(isChangeSecondHandle, pattern->TriggerAvoidOnCaretChange());
if (isFirst) {
pattern->textSelector_.firstHandle.SetOffset(localOffset);
} else {

View File

@ -2394,7 +2394,7 @@ void PipelineContext::DoKeyboardAvoidFunc(float keyboardHeight, double positionY
height = rootSize.Height() - positionY;
}
auto lastKeyboardOffset = safeAreaManager_->GetKeyboardOffsetDirectly();
auto newKeyboardOffset = CalcAvoidOffset(keyboardHeight, positionY, height, rootSize);
auto newKeyboardOffset = CalcNewKeyboardOffset(keyboardHeight, positionY, height, rootSize);
if (NearZero(keyboardHeight) || LessOrEqual(newKeyboardOffset, lastKeyboardOffset) ||
(manager->GetOnFocusTextFieldId() == manager->GetLastAvoidFieldId() && !keyboardHeightChanged)) {
safeAreaManager_->UpdateKeyboardOffset(newKeyboardOffset);
@ -2420,6 +2420,26 @@ void PipelineContext::DoKeyboardAvoidFunc(float keyboardHeight, double positionY
}
}
float PipelineContext::CalcNewKeyboardOffset(float keyboardHeight, float positionY,
float height, SizeF& rootSize)
{
auto newKeyboardOffset = CalcAvoidOffset(keyboardHeight, positionY, height, rootSize);
CHECK_NULL_RETURN(safeAreaManager_, newKeyboardOffset);
auto manager = DynamicCast<TextFieldManagerNG>(PipelineBase::GetTextFieldManager());
CHECK_NULL_RETURN(manager, newKeyboardOffset);
auto onFocusField = manager->GetOnFocusTextField().Upgrade();
CHECK_NULL_RETURN(onFocusField, newKeyboardOffset);
auto host = onFocusField->GetHost();
CHECK_NULL_RETURN(host, newKeyboardOffset);
auto geometryNode = host->GetGeometryNode();
CHECK_NULL_RETURN(geometryNode, newKeyboardOffset);
auto paintOffset = host->GetPaintRectOffset();
auto frameSize = geometryNode->GetFrameSize();
auto offset = CalcAvoidOffset(keyboardHeight, paintOffset.GetY() - safeAreaManager_->GetKeyboardOffsetDirectly(),
frameSize.Height(), rootSize);
return std::max(offset, newKeyboardOffset);
}
float PipelineContext::CalcAvoidOffset(float keyboardHeight, float positionY,
float height, SizeF rootSize)
{

View File

@ -375,6 +375,8 @@ public:
const std::shared_ptr<Rosen::RSTransaction>& rsTransaction = nullptr, bool forceChange = false);
void DoKeyboardAvoidFunc(float keyboardHeight, double positionY, double height,
bool keyboardHeightChanged);
float CalcNewKeyboardOffset(float keyboardHeight, float positionYWithOffset,
float height, SizeF& rootSize);
float CalcAvoidOffset(float keyboardHeight, float positionYWithOffset,
float height, SizeF rootSize);

View File

@ -960,7 +960,7 @@ HWTEST_F(RichEditorClickTestNg, MoveCaretOnLayoutSwap, TestSize.Level1)
richEditorPattern->isTextChange_ = true;
richEditorPattern->moveDirection_ = MoveDirection::FORWARD;
richEditorPattern->moveLength_ = 1;
richEditorPattern->MoveCaretOnLayoutSwap(true);
richEditorPattern->MoveCaretOnLayoutSwap();
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 1);
EXPECT_EQ(richEditorPattern->moveLength_, 0);
EXPECT_FALSE(richEditorPattern->isTextChange_);