• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "core/components_ng/pattern/text_field/auto_fill_controller.h"
16 
17 #include <algorithm>
18 #include <cstdint>
19 #include <string>
20 
21 #include "base/utils/string_utils.h"
22 #include "base/utils/utf_helper.h"
23 #include "base/utils/utils.h"
24 #include "core/components_ng/pattern/text/text_layout_property.h"
25 #include "core/components_ng/pattern/text/text_pattern.h"
26 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
27 
28 namespace OHOS::Ace::NG {
29 namespace {
30 constexpr int32_t AUTO_FILL_ICON_ANIMATION_DURATION = 250;
31 constexpr float AUTO_FILL_SPRING_RESPONSE = 0.513f;
32 constexpr float AUTO_FILL_SPRING_DAMPING_FRACTION = 0.94f;
33 constexpr float AUTO_FILL_SPRING_RESPONSE_EXTRA_LONG = 0.613f;
34 constexpr float AUTO_FILL_SPRING_DAMPING_FRACTION_EXTRA_LONG = 0.93f;
35 constexpr uint32_t AUTO_FILL_SYMBOL_RENDERING_STRATEGY = 1;
36 constexpr float AUTO_FILL_ICON_INIT_SCALE = 0.2f;
37 constexpr int32_t AUTO_FILL_TEXT_SCROLL_DELAY_DURATION = 500;
38 constexpr int32_t AUTO_FILL_DEFAULT_CHAR_DELAY_DURATION = 150;
39 constexpr int32_t AUTO_FILL_ICON_HIDE_DELAY_DURATION_SHORT = 800;
40 constexpr int32_t AUTO_FILL_ICON_HIDE_DELAY_DURATION_MEDIUM = 900;
41 constexpr int32_t AUTO_FILL_ICON_HIDE_DELAY_DURATION_LONG = 1000;
42 constexpr int32_t AUTO_FILL_ICON_HIDE_DELAY_DURATION_EXTRA_LONG = 1100;
43 } // namespace
44 
StartAutoFillAnimation(const std::function<void ()> & onFinishCallback,const std::u16string & content)45 void AutoFillController::StartAutoFillAnimation(
46     const std::function<void()>& onFinishCallback, const std::u16string& content)
47 {
48     auto initParagraphSuc = InitAutoFillParagraph(content);
49     auto createAutoFillIconSuc = CreateAutoFillIcon();
50     if (!initParagraphSuc || !createAutoFillIconSuc) {
51         if (onFinishCallback) {
52             onFinishCallback();
53         }
54         ResetAutoFillAnimationStatus();
55         return;
56     }
57     AutoFillContentLengthMode mode = GetAutoFillContentLengthMode();
58     if (mode == AutoFillContentLengthMode::INVALID) {
59         if (onFinishCallback) {
60             onFinishCallback();
61         }
62         ResetAutoFillAnimationStatus();
63         return;
64     }
65     auto pattern = pattern_.Upgrade();
66     CHECK_NULL_VOID(pattern);
67     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
68     CHECK_NULL_VOID(textFieldPattern);
69     textFieldPattern->StopTwinkling();
70     UpdateAnimationTextRect();
71     if (mode == AutoFillContentLengthMode::EXTRA_LONG) {
72         PlayAutoFillIconShowAnimation(mode);
73         PlayAutoFillTextScrollAnimation();
74         PlayAutoFillIconHideAnimation(onFinishCallback, mode);
75     } else {
76         PlayAutoFillIconShowAnimation(mode);
77         PlayAutoFillIconHideAnimation(onFinishCallback, mode);
78     }
79 }
80 
GetAutoFillContentLengthMode()81 AutoFillContentLengthMode AutoFillController::GetAutoFillContentLengthMode()
82 {
83     auto pattern = pattern_.Upgrade();
84     CHECK_NULL_RETURN(pattern, AutoFillContentLengthMode::INVALID);
85     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
86     CHECK_NULL_RETURN(textFieldPattern, AutoFillContentLengthMode::INVALID);
87     CHECK_NULL_RETURN(autoFillParagraph_, AutoFillContentLengthMode::INVALID);
88 
89     float autoFillParagraphWidth = std::max(autoFillParagraph_->GetLongestLine(), 0.0f);
90     auto contentRect = textFieldPattern->GetTextContentRect();
91     float textFieldContentWidth = std::max(contentRect.Width(), 0.0f);
92     if (LessOrEqual(autoFillParagraphWidth, 0.0f) || LessOrEqual(textFieldContentWidth, 0.0f)) {
93         return AutoFillContentLengthMode::INVALID;
94     }
95 
96     if (GreatNotEqual(autoFillParagraphWidth, textFieldContentWidth)) {
97         return AutoFillContentLengthMode::EXTRA_LONG;
98     }
99 
100     auto shortContentLength = textFieldContentWidth * 1.0f / 3.0f;
101     auto middleContentLength = textFieldContentWidth * 2.0f / 3.0f;
102     if (LessOrEqual(autoFillParagraphWidth, shortContentLength)) {
103         return AutoFillContentLengthMode::SHORT;
104     }
105 
106     if (LessOrEqual(autoFillParagraphWidth, middleContentLength)) {
107         return AutoFillContentLengthMode::MEDIUM;
108     }
109 
110     return AutoFillContentLengthMode::LONG;
111 }
112 
InitAutoFillParagraph(const std::u16string & content)113 bool AutoFillController::InitAutoFillParagraph(const std::u16string& content)
114 {
115     auto pattern = pattern_.Upgrade();
116     CHECK_NULL_RETURN(pattern, false);
117     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
118     CHECK_NULL_RETURN(textFieldPattern, false);
119     autoFillParagraph_ = textFieldPattern->GetParagraph();
120     CHECK_NULL_RETURN(autoFillParagraph_, false);
121     auto textFieldContentModifier = textFieldPattern->GetContentModifier();
122     CHECK_NULL_RETURN(textFieldContentModifier, false);
123     textFieldContentModifier->SetAutoFillOriginTextColor(autoFillOriginTextColor_);
124     return true;
125 }
126 
PlayAutoFillIconShowAnimation(const AutoFillContentLengthMode & mode)127 void AutoFillController::PlayAutoFillIconShowAnimation(const AutoFillContentLengthMode& mode)
128 {
129     auto symbolNode = autoFillIconNode_.Upgrade();
130     CHECK_NULL_VOID(symbolNode);
131     auto symbolRenderContext = symbolNode->GetRenderContext();
132     CHECK_NULL_VOID(symbolRenderContext);
133     AnimationOption option = AnimationOption();
134     option.SetDuration(AUTO_FILL_ICON_ANIMATION_DURATION);
135     option.SetCurve(Curves::FRICTION);
136     AnimationUtils::Animate(
137         option,
138         [symbolRenderContext]() {
139             symbolRenderContext->UpdateOpacity(1.0);
140             symbolRenderContext->UpdateTransformScale({ 1.0, 1.0 });
141         },
142         [weak = AceType::WeakClaim(this), mode]() {
143             auto autofillController = weak.Upgrade();
144             CHECK_NULL_VOID(autofillController);
145             autofillController->PlayAutoFillTranslationAnimation(mode);
146             autofillController->PlayAutoFillDefaultCharAnimation(mode);
147         }, nullptr, symbolNode->GetContextRefPtr());
148 }
149 
PlayAutoFillDefaultCharAnimation(const AutoFillContentLengthMode & mode)150 void AutoFillController::PlayAutoFillDefaultCharAnimation(const AutoFillContentLengthMode& mode)
151 {
152     if (!autoFillParagraph_) {
153         ResetAutoFillAnimationStatus();
154         return;
155     }
156     auto pattern = pattern_.Upgrade();
157     CHECK_NULL_VOID(pattern);
158     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
159     CHECK_NULL_VOID(textFieldPattern);
160     auto contentLength = autoFillParagraph_->GetParagraphText().length();
161     auto response = GetSpringAnimationResponse(mode);
162     auto damping = GetSpringAnimationDamping(mode);
163     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, damping);
164     AnimationOption option;
165     option.SetCurve(motion);
166     option.SetDelay(AUTO_FILL_DEFAULT_CHAR_DELAY_DURATION);
167     AnimationUtils::Animate(option, [weak = AceType::WeakClaim(this), weakPattern = pattern_, contentLength]() {
168         auto autofillController = weak.Upgrade();
169         CHECK_NULL_VOID(autofillController);
170         auto pattern = weakPattern.Upgrade();
171         CHECK_NULL_VOID(pattern);
172         auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
173         CHECK_NULL_VOID(textFieldPattern);
174         auto textFieldContentModifier = textFieldPattern->GetContentModifier();
175         CHECK_NULL_VOID(textFieldContentModifier);
176         autofillController->autoFillAnimationStatus_ = AutoFillAnimationStatus::TRANSLATION;
177         textFieldContentModifier->SetAutoFillDefaultCharIndex(std::max(contentLength - 1.0f, 0.0f));
178     }, nullptr, nullptr, Claim(pattern->GetContext()));
179 }
180 
PlayAutoFillTranslationAnimation(const AutoFillContentLengthMode & mode)181 void AutoFillController::PlayAutoFillTranslationAnimation(const AutoFillContentLengthMode& mode)
182 {
183     if (!autoFillParagraph_) {
184         ResetAutoFillAnimationStatus();
185         return;
186     }
187     auto pattern = pattern_.Upgrade();
188     CHECK_NULL_VOID(pattern);
189     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
190     CHECK_NULL_VOID(textFieldPattern);
191     auto symbolNode = autoFillIconNode_.Upgrade();
192     CHECK_NULL_VOID(symbolNode);
193     auto symbolRenderContext = symbolNode->GetRenderContext();
194     CHECK_NULL_VOID(symbolRenderContext);
195     float autoFillParagraphWidth = std::max(autoFillParagraph_->GetLongestLine(), 0.0f);
196     auto contentRect = textFieldPattern->GetTextContentRect();
197     float textFieldContentWidth = std::max(contentRect.Width(), 0.0f);
198     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
199     CHECK_NULL_VOID(layoutProperty);
200     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
201     auto theme = textFieldPattern->GetTheme();
202     CHECK_NULL_VOID(theme);
203     auto iconSize = theme->GetAutoFillIconSize();
204     auto iconWidth = static_cast<float>(iconSize.ConvertToPx());
205     auto translationOffset =
206         std::min(autoFillParagraphWidth + autoFillFirstCharOffset_, textFieldContentWidth - iconWidth);
207     if (isRTL) {
208         translationOffset = -translationOffset;
209     }
210     auto contentLength = autoFillParagraph_->GetParagraphText().length();
211     auto response = GetSpringAnimationResponse(mode);
212     auto damping = GetSpringAnimationDamping(mode);
213     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, damping);
214     AnimationOption option;
215     option.SetCurve(motion);
216     AnimationUtils::Animate(option, [weak = AceType::WeakClaim(this), weakPattern = pattern_, translationOffset,
217                                         symbolRenderContext, contentLength]() {
218         auto autofillController = weak.Upgrade();
219         CHECK_NULL_VOID(autofillController);
220         auto pattern = weakPattern.Upgrade();
221         CHECK_NULL_VOID(pattern);
222         auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
223         CHECK_NULL_VOID(textFieldPattern);
224         auto textFieldContentModifier = textFieldPattern->GetContentModifier();
225         CHECK_NULL_VOID(textFieldContentModifier);
226         autofillController->autoFillAnimationStatus_ = AutoFillAnimationStatus::TRANSLATION;
227         textFieldContentModifier->SetAutoFillEmphasizeCharIndex(std::max(contentLength - 1.0f, 0.0f));
228         textFieldContentModifier->SetAutoFillTranslationOffset(translationOffset);
229         symbolRenderContext->UpdateTransformTranslate({ translationOffset, 0.0f, 0.0f });
230     }, nullptr, nullptr, Claim(pattern->GetContext()));
231 }
232 
PlayAutoFillTextScrollAnimation()233 void AutoFillController::PlayAutoFillTextScrollAnimation()
234 {
235     if (!autoFillParagraph_) {
236         ResetAutoFillAnimationStatus();
237         return;
238     }
239     auto pattern = pattern_.Upgrade();
240     CHECK_NULL_VOID(pattern);
241     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
242     CHECK_NULL_VOID(textFieldPattern);
243     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
244     CHECK_NULL_VOID(layoutProperty);
245     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
246     float autoFillParagraphWidth = std::max(autoFillParagraph_->GetLongestLine(), 0.0f);
247     auto contentRect = textFieldPattern->GetTextContentRect();
248     float textFieldContentWidth = std::max(contentRect.Width(), 0.0f);
249     auto startScrollOffset = isRTL ? autoFillParagraphWidth - textFieldContentWidth : 0;
250     auto endScrollOffset = isRTL ? 0 : autoFillParagraphWidth - textFieldContentWidth;
251     auto textFieldContentModifier = textFieldPattern->GetContentModifier();
252     CHECK_NULL_VOID(textFieldContentModifier);
253     textFieldContentModifier->SetAutoFillTextScrollOffset(startScrollOffset);
254     auto motion = AceType::MakeRefPtr<ResponsiveSpringMotion>(
255         AUTO_FILL_SPRING_RESPONSE_EXTRA_LONG, AUTO_FILL_SPRING_DAMPING_FRACTION_EXTRA_LONG);
256     AnimationOption option;
257     option.SetCurve(motion);
258     option.SetDelay(AUTO_FILL_TEXT_SCROLL_DELAY_DURATION);
259     AnimationUtils::Animate(option, [weak = AceType::WeakClaim(this), weakPattern = pattern_, endScrollOffset]() {
260         auto autofillController = weak.Upgrade();
261         CHECK_NULL_VOID(autofillController);
262         auto pattern = weakPattern.Upgrade();
263         CHECK_NULL_VOID(pattern);
264         auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
265         CHECK_NULL_VOID(textFieldPattern);
266         auto textFieldContentModifier = textFieldPattern->GetContentModifier();
267         CHECK_NULL_VOID(textFieldContentModifier);
268         autofillController->autoFillAnimationStatus_ = AutoFillAnimationStatus::TRANSLATION;
269         textFieldContentModifier->SetAutoFillTextScrollOffset(endScrollOffset);
270     }, nullptr, nullptr, Claim(pattern->GetContext()));
271 }
272 
PlayAutoFillIconHideAnimation(const std::function<void ()> & onFinishCallback,const AutoFillContentLengthMode & mode)273 void AutoFillController::PlayAutoFillIconHideAnimation(
274     const std::function<void()>& onFinishCallback, const AutoFillContentLengthMode& mode)
275 {
276     auto symbolNode = autoFillIconNode_.Upgrade();
277     if (!symbolNode) {
278         ResetAutoFillAnimationStatus();
279         return;
280     }
281     auto symbolRenderContext = symbolNode->GetRenderContext();
282     if (!symbolRenderContext) {
283         ResetAutoFillAnimationStatus();
284         return;
285     }
286     auto delayDuration = AUTO_FILL_ICON_HIDE_DELAY_DURATION_SHORT;
287     if (mode == AutoFillContentLengthMode::MEDIUM) {
288         delayDuration = AUTO_FILL_ICON_HIDE_DELAY_DURATION_MEDIUM;
289     } else if (mode == AutoFillContentLengthMode::LONG) {
290         delayDuration = AUTO_FILL_ICON_HIDE_DELAY_DURATION_LONG;
291     } else if (mode == AutoFillContentLengthMode::EXTRA_LONG) {
292         delayDuration = AUTO_FILL_ICON_HIDE_DELAY_DURATION_EXTRA_LONG;
293     }
294 
295     AnimationOption option = AnimationOption();
296     option.SetDuration(AUTO_FILL_ICON_ANIMATION_DURATION);
297     option.SetCurve(Curves::FRICTION);
298     option.SetDelay(delayDuration);
299     AnimationUtils::Animate(
300         option,
301         [weak = AceType::WeakClaim(this), symbolRenderContext]() {
302             auto autofillController = weak.Upgrade();
303             CHECK_NULL_VOID(autofillController);
304             autofillController->autoFillAnimationStatus_ = AutoFillAnimationStatus::HIDE_ICON;
305             symbolRenderContext->UpdateOpacity(0.0);
306             symbolRenderContext->UpdateTransformScale({ AUTO_FILL_ICON_INIT_SCALE, AUTO_FILL_ICON_INIT_SCALE });
307         },
308         [weak = AceType::WeakClaim(this), weakPattern = pattern_, onFinish = std::move(onFinishCallback)]() {
309             auto autofillController = weak.Upgrade();
310             CHECK_NULL_VOID(autofillController);
311             auto pattern = weakPattern.Upgrade();
312             CHECK_NULL_VOID(pattern);
313             auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
314             CHECK_NULL_VOID(textFieldPattern);
315             autofillController->ResetAutoFillAnimationStatus();
316             autofillController->ResetAutoFillIcon();
317             textFieldPattern->StartTwinkling();
318             if (onFinish) {
319                 onFinish();
320             }
321         }, nullptr, symbolNode->GetContextRefPtr());
322 }
323 
CreateAutoFillIcon()324 bool AutoFillController::CreateAutoFillIcon()
325 {
326     auto pattern = pattern_.Upgrade();
327     CHECK_NULL_RETURN(pattern, false);
328     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
329     CHECK_NULL_RETURN(textFieldPattern, false);
330     auto host = textFieldPattern->GetHost();
331     CHECK_NULL_RETURN(host, false);
332     auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
333         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
334     CHECK_NULL_RETURN(symbolNode, false);
335     autoFillIconNode_ = WeakClaim(RawPtr(symbolNode));
336     auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
337     CHECK_NULL_RETURN(symbolProperty, false);
338     auto theme = textFieldPattern->GetTheme();
339     CHECK_NULL_RETURN(theme, false);
340     symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(theme->GetAutoFillSymbolId()));
341     symbolProperty->UpdateFontSize(theme->GetAutoFillIconSize());
342     symbolProperty->UpdateSymbolColorList(
343         { theme->GetAutoFillIconPrimaryColor(), theme->GetAutoFillIconEmphasizeColor() });
344     symbolProperty->UpdateSymbolRenderingStrategy(AUTO_FILL_SYMBOL_RENDERING_STRATEGY);
345     auto symbolRenderContext = symbolNode->GetRenderContext();
346     CHECK_NULL_RETURN(symbolRenderContext, false);
347     symbolRenderContext->UpdateOpacity(0.0);
348     symbolRenderContext->UpdateTransformScale({ AUTO_FILL_ICON_INIT_SCALE, AUTO_FILL_ICON_INIT_SCALE });
349     CHECK_NULL_RETURN(autoFillParagraph_, false);
350     auto layoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
351     CHECK_NULL_RETURN(layoutProperty, false);
352     auto isRTL = layoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
353     auto lineMetrics = autoFillParagraph_->GetLineMetrics(0);
354     autoFillFirstCharOffset_ = lineMetrics.x;
355     auto startOffset = autoFillFirstCharOffset_;
356     auto contentRect = textFieldPattern->GetTextContentRect();
357     if (isRTL) {
358         // animation from right to left
359         startOffset = contentRect.Width() - (startOffset + lineMetrics.width);
360         startOffset = std::max(startOffset, 0.0f);
361         autoFillFirstCharOffset_ = startOffset;
362         startOffset = -startOffset;
363     }
364     symbolRenderContext->UpdateTransformTranslate({ startOffset, 0.0f, 0.0f });
365     symbolNode->MountToParent(host);
366     symbolNode->MarkModifyDone();
367     symbolNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
368     return true;
369 }
370 
ResetAutoFillIcon()371 void AutoFillController::ResetAutoFillIcon()
372 {
373     auto pattern = pattern_.Upgrade();
374     CHECK_NULL_VOID(pattern);
375     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
376     CHECK_NULL_VOID(textFieldPattern);
377     auto host = textFieldPattern->GetHost();
378     CHECK_NULL_VOID(host);
379     auto symbolNode = autoFillIconNode_.Upgrade();
380     CHECK_NULL_VOID(symbolNode);
381     host->RemoveChild(symbolNode);
382     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
383 }
384 
ResetAutoFillAnimationStatus()385 void AutoFillController::ResetAutoFillAnimationStatus()
386 {
387     autoFillAnimationStatus_ = AutoFillAnimationStatus::INIT;
388     if (autoFillParagraph_) {
389         autoFillParagraph_ = nullptr;
390     }
391     auto pattern = pattern_.Upgrade();
392     CHECK_NULL_VOID(pattern);
393     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
394     CHECK_NULL_VOID(textFieldPattern);
395     auto textFieldContentModifier = textFieldPattern->GetContentModifier();
396     CHECK_NULL_VOID(textFieldContentModifier);
397     textFieldContentModifier->SetAutoFillTranslationOffset(0.0f);
398     textFieldContentModifier->SetAutoFillTextScrollOffset(0.0f);
399     textFieldContentModifier->SetAutoFillEmphasizeCharIndex(0.0f);
400     textFieldContentModifier->SetAutoFillDefaultCharIndex(0.0f);
401 }
402 
GetSpringAnimationResponse(const AutoFillContentLengthMode & mode)403 float AutoFillController::GetSpringAnimationResponse(const AutoFillContentLengthMode& mode)
404 {
405     return mode == AutoFillContentLengthMode::EXTRA_LONG ? AUTO_FILL_SPRING_RESPONSE_EXTRA_LONG
406                                                          : AUTO_FILL_SPRING_RESPONSE;
407 }
408 
GetSpringAnimationDamping(const AutoFillContentLengthMode & mode)409 float AutoFillController::GetSpringAnimationDamping(const AutoFillContentLengthMode& mode)
410 {
411     return mode == AutoFillContentLengthMode::EXTRA_LONG ? AUTO_FILL_SPRING_DAMPING_FRACTION_EXTRA_LONG
412                                                          : AUTO_FILL_SPRING_DAMPING_FRACTION;
413 }
414 
UpdateAnimationTextRect()415 void AutoFillController::UpdateAnimationTextRect()
416 {
417     auto pattern = pattern_.Upgrade();
418     CHECK_NULL_VOID(pattern);
419     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern);
420     CHECK_NULL_VOID(textFieldPattern);
421     auto textRect = textFieldPattern->GetTextRect();
422     auto contentRect = textFieldPattern->GetTextContentRect();
423     animationTextRect_ = textRect;
424     animationTextRect_.SetLeft(contentRect.GetX());
425 }
426 } // namespace OHOS::Ace::NG