• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 
16 #include "core/components_ng/pattern/tabs/tab_bar_pattern.h"
17 
18 #include <optional>
19 
20 #include "base/geometry/axis.h"
21 #include "base/geometry/dimension.h"
22 #include "base/geometry/ng/offset_t.h"
23 #include "base/geometry/ng/size_t.h"
24 #include "base/log/dump_log.h"
25 #include "base/memory/ace_type.h"
26 #include "base/utils/utils.h"
27 #include "core/common/agingadapation/aging_adapation_dialog_util.h"
28 #include "core/components/common/layout/constants.h"
29 #include "core/components_ng/pattern/scrollable/scrollable.h"
30 #include "core/components/tab_bar/tab_theme.h"
31 #include "core/components_ng/base/frame_node.h"
32 #include "core/components_ng/base/inspector_filter.h"
33 #include "core/components_ng/pattern/image/image_layout_property.h"
34 #include "core/components_ng/pattern/pattern.h"
35 #include "core/components_ng/pattern/scroll/scroll_spring_effect.h"
36 #include "core/components_ng/pattern/swiper/swiper_event_hub.h"
37 #include "core/components_ng/pattern/swiper/swiper_model.h"
38 #include "core/components_ng/pattern/tabs/tabs_controller.h"
39 #include "core/components_ng/pattern/tabs/tabs_layout_property.h"
40 #include "core/components_ng/pattern/tabs/tabs_node.h"
41 #include "core/components_ng/pattern/tabs/tabs_pattern.h"
42 #include "core/components_ng/pattern/tabs/tab_content_model_ng.h"
43 #include "core/components_ng/pattern/text/text_layout_property.h"
44 #include "base/perfmonitor/perf_constants.h"
45 #include "base/perfmonitor/perf_monitor.h"
46 namespace OHOS::Ace::NG {
47 namespace {
48 constexpr int8_t LEFT_GRADIENT = 0;
49 constexpr int8_t RIGHT_GRADIENT = 1;
50 constexpr int8_t TOP_GRADIENT = 2;
51 constexpr int8_t BOTTOM_GRADIENT = 3;
52 constexpr float HALF_PROGRESS = 0.5f;
53 constexpr float FULL_PROGRESS = 1.0f;
54 constexpr float HALF_MASK_RADIUS_RATIO = 0.717f;
55 constexpr float FULL_MASK_RADIUS_RATIO = 1.414f;
56 constexpr float INVALID_RATIO = -1.0f;
57 constexpr uint16_t MASK_ANIMATION_DURATION = 200;
58 constexpr int8_t MASK_COUNT = 2;
59 constexpr float FULL_OPACITY = 1.0f;
60 constexpr float NEAR_FULL_OPACITY = 0.99f;
61 constexpr float NO_OPACITY = 0.0f;
62 constexpr float TEXT_COLOR_THREDHOLD = 0.673f;
63 constexpr int8_t HALF_OF_WIDTH = 2;
64 constexpr float MAX_FLING_VELOCITY = 4200.0f;
65 
66 const auto DurationCubicCurve = AceType::MakeRefPtr<CubicCurve>(0.2f, 0.0f, 0.1f, 1.0f);
67 const auto TRANSLATE_CURVE = AceType::MakeRefPtr<InterpolatingSpring>(0.0f, 1.0f, 228.0f, 30.0f);
68 const auto TRANSLATE_THRESHOLD = 26.0f;
69 const auto TRANSLATE_FRAME_RATE = 120;
70 const auto TRANSLATE_FRAME_RATE_RANGE =
71     AceType::MakeRefPtr<FrameRateRange>(0, TRANSLATE_FRAME_RATE, TRANSLATE_FRAME_RATE);
72 const std::string TAB_BAR_PROPERTY_NAME = "tabBar";
73 const std::string INDICATOR_OFFSET_PROPERTY_NAME = "indicatorOffset";
74 const std::string INDICATOR_WIDTH_PROPERTY_NAME = "translateWidth";
75 } // namespace
76 
77 TabBarPattern::TabBarPattern() = default;
78 
79 TabBarPattern::~TabBarPattern() = default;
80 
SetController(const RefPtr<SwiperController> & controller)81 void TabBarPattern::SetController(const RefPtr<SwiperController>& controller)
82 {
83     swiperController_ = controller;
84     SetTabBarFinishCallback();
85     auto tabsController = AceType::DynamicCast<TabsControllerNG>(swiperController_);
86     CHECK_NULL_VOID(tabsController);
87     auto weak = WeakClaim(this);
88     tabsController->SetStartShowTabBarImpl([weak](int32_t delay) {
89         auto pattern = weak.Upgrade();
90         CHECK_NULL_VOID(pattern);
91         pattern->StartShowTabBar(delay);
92     });
93     tabsController->SetCancelShowTabBarImpl([weak]() {
94         auto pattern = weak.Upgrade();
95         CHECK_NULL_VOID(pattern);
96         pattern->CancelShowTabBar();
97     });
98     tabsController->SetUpdateTabBarHiddenOffsetImpl([weak](float offset) {
99         auto pattern = weak.Upgrade();
100         CHECK_NULL_VOID(pattern);
101         pattern->UpdateTabBarHiddenOffset(offset);
102     });
103     tabsController->SetTabBarTranslateImpl([weak](const TranslateOptions& options) {
104         auto pattern = weak.Upgrade();
105         CHECK_NULL_VOID(pattern);
106         pattern->SetTabBarTranslate(options);
107     });
108     tabsController->SetTabBarOpacityImpl([weak](float opacity) {
109         auto pattern = weak.Upgrade();
110         CHECK_NULL_VOID(pattern);
111         pattern->SetTabBarOpacity(opacity);
112     });
113 }
114 
StartShowTabBar(int32_t delay)115 void TabBarPattern::StartShowTabBar(int32_t delay)
116 {
117     if (axis_ == Axis::VERTICAL || isTabBarShowing_) {
118         return;
119     }
120     auto host = GetHost();
121     CHECK_NULL_VOID(host);
122     auto renderContext = host->GetRenderContext();
123     CHECK_NULL_VOID(renderContext);
124     auto options = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
125     auto translate = options.y.ConvertToPx();
126     auto size = renderContext->GetPaintRectWithoutTransform().Height();
127     if (NearZero(translate) || NearZero(size)) {
128         return;
129     }
130 
131     CancelShowTabBar();
132     if (delay == 0 && isTabBarHiding_) {
133         // stop hide tab bar and show tab bar immediately.
134         StopHideTabBar();
135     } else if (delay > 0 && !isTabBarHiding_) {
136         auto threshold = Dimension(TRANSLATE_THRESHOLD, DimensionUnit::VP).ConvertToPx();
137         if (tabBarState_ == TabBarState::SHOW && LessNotEqual(std::abs(translate), threshold)) {
138             // not reach the threshold for hiding tab bar, so show tab bar immediately.
139             delay = 0;
140         } else if (tabBarState_ == TabBarState::HIDE && LessNotEqual(size - std::abs(translate), threshold)) {
141             // not reach the threshold for showing tab bar, so hide tab bar immediately and show tab bar after 2s.
142             StartHideTabBar();
143         }
144     }
145 
146     if (delay == 0) {
147         StartShowTabBarImmediately();
148     }
149 }
150 
StartShowTabBarImmediately()151 void TabBarPattern::StartShowTabBarImmediately()
152 {
153     auto host = GetHost();
154     CHECK_NULL_VOID(host);
155     auto renderContext = host->GetRenderContext();
156     CHECK_NULL_VOID(renderContext);
157 
158     InitTabBarProperty();
159     AnimationOption option;
160     option.SetCurve(TRANSLATE_CURVE);
161     option.SetFrameRateRange(TRANSLATE_FRAME_RATE_RANGE);
162 
163     auto options = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
164     auto translate = options.y.ConvertToPx();
165     tabBarProperty_->Set(translate);
166     auto propertyCallback = [weak = WeakClaim(this)]() {
167         auto pattern = weak.Upgrade();
168         CHECK_NULL_VOID(pattern);
169         pattern->tabBarProperty_->Set(0.0f);
170     };
171     auto finishCallback = [weak = WeakClaim(this)]() {
172         auto pattern = weak.Upgrade();
173         CHECK_NULL_VOID(pattern);
174         pattern->isTabBarShowing_ = false;
175         pattern->tabBarState_ = TabBarState::SHOW;
176     };
177     AnimationUtils::Animate(option, propertyCallback, finishCallback);
178     isTabBarShowing_ = true;
179 }
180 
CancelShowTabBar()181 void TabBarPattern::CancelShowTabBar()
182 {
183     if (showTabBarTask_) {
184         showTabBarTask_.Cancel();
185         showTabBarTask_.Reset(nullptr);
186     }
187 }
188 
StartHideTabBar()189 void TabBarPattern::StartHideTabBar()
190 {
191     if (axis_ == Axis::VERTICAL || showTabBarTask_ || isTabBarShowing_ || isTabBarHiding_) {
192         return;
193     }
194     auto host = GetHost();
195     CHECK_NULL_VOID(host);
196     auto renderContext = host->GetRenderContext();
197     CHECK_NULL_VOID(renderContext);
198     auto options = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
199     auto translate = options.y.ConvertToPx();
200     auto size = renderContext->GetPaintRectWithoutTransform().Height();
201     if (GreatOrEqual(std::abs(translate), size) || NearZero(size)) {
202         return;
203     }
204 
205     InitTabBarProperty();
206     AnimationOption option;
207     option.SetCurve(TRANSLATE_CURVE);
208     option.SetFrameRateRange(TRANSLATE_FRAME_RATE_RANGE);
209 
210     tabBarProperty_->Set(translate);
211     auto propertyCallback = [weak = WeakClaim(this), size]() {
212         auto pattern = weak.Upgrade();
213         CHECK_NULL_VOID(pattern);
214         auto host = pattern->GetHost();
215         CHECK_NULL_VOID(host);
216         auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
217         CHECK_NULL_VOID(tabsNode);
218         auto tabsLayoutProperty = AceType::DynamicCast<TabsLayoutProperty>(tabsNode->GetLayoutProperty());
219         CHECK_NULL_VOID(tabsLayoutProperty);
220         auto barPosition = tabsLayoutProperty->GetTabBarPosition().value_or(BarPosition::START);
221         if (barPosition == BarPosition::START) {
222             pattern->tabBarProperty_->Set(-size);
223         } else {
224             pattern->tabBarProperty_->Set(size);
225         }
226     };
227     auto finishCallback = [weak = WeakClaim(this)]() {
228         auto pattern = weak.Upgrade();
229         CHECK_NULL_VOID(pattern);
230         pattern->isTabBarHiding_ = false;
231         pattern->tabBarState_ = TabBarState::HIDE;
232     };
233     AnimationUtils::Animate(option, propertyCallback, finishCallback);
234     isTabBarHiding_ = true;
235 }
236 
StopHideTabBar()237 void TabBarPattern::StopHideTabBar()
238 {
239     if (axis_ == Axis::VERTICAL || !isTabBarHiding_) {
240         return;
241     }
242     auto host = GetHost();
243     CHECK_NULL_VOID(host);
244     auto renderContext = host->GetRenderContext();
245     CHECK_NULL_VOID(renderContext);
246 
247     AnimationOption option;
248     option.SetDuration(0);
249     option.SetCurve(Curves::LINEAR);
250     auto options = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
251     auto translate = options.y.ConvertToPx();
252     auto propertyCallback = [weak = WeakClaim(this), translate]() {
253         auto pattern = weak.Upgrade();
254         CHECK_NULL_VOID(pattern);
255         pattern->tabBarProperty_->Set(translate);
256     };
257     AnimationUtils::Animate(option, propertyCallback);
258     isTabBarHiding_ = false;
259 }
260 
InitTabBarProperty()261 void TabBarPattern::InitTabBarProperty()
262 {
263     if (tabBarProperty_) {
264         return;
265     }
266     auto host = GetHost();
267     CHECK_NULL_VOID(host);
268     auto renderContext = host->GetRenderContext();
269     CHECK_NULL_VOID(renderContext);
270 
271     auto propertyCallback = [weak = WeakClaim(this)](float value) {
272         auto pattern = weak.Upgrade();
273         CHECK_NULL_VOID(pattern);
274         auto host = pattern->GetHost();
275         CHECK_NULL_VOID(host);
276         auto renderContext = host->GetRenderContext();
277         CHECK_NULL_VOID(renderContext);
278 
279         pattern->SetTabBarTranslate(TranslateOptions(0.0f, value, 0.0f));
280         auto size = renderContext->GetPaintRectWithoutTransform().Height();
281         if (NearZero(size)) {
282             return;
283         }
284         pattern->SetTabBarOpacity(1.0f - std::abs(value) / size);
285     };
286     tabBarProperty_ = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(0.0, std::move(propertyCallback));
287     renderContext->AttachNodeAnimatableProperty(tabBarProperty_);
288 }
289 
UpdateTabBarHiddenOffset(float offset)290 void TabBarPattern::UpdateTabBarHiddenOffset(float offset)
291 {
292     if (axis_ == Axis::VERTICAL || showTabBarTask_ || isTabBarShowing_ || isTabBarHiding_) {
293         return;
294     }
295     auto host = GetHost();
296     CHECK_NULL_VOID(host);
297     auto renderContext = host->GetRenderContext();
298     CHECK_NULL_VOID(renderContext);
299     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
300     CHECK_NULL_VOID(tabsNode);
301     auto tabsLayoutProperty = AceType::DynamicCast<TabsLayoutProperty>(tabsNode->GetLayoutProperty());
302     CHECK_NULL_VOID(tabsLayoutProperty);
303 
304     auto options = renderContext->GetTransformTranslateValue(TranslateOptions(0.0f, 0.0f, 0.0f));
305     float preTranslate = options.y.ConvertToPx();
306     auto size = renderContext->GetPaintRectWithoutTransform().Height();
307     if (NearZero(size)) {
308         return;
309     }
310     auto barPosition = tabsLayoutProperty->GetTabBarPosition().value_or(BarPosition::START);
311     auto translate = 0.0f;
312     if (barPosition == BarPosition::START) {
313         translate = std::clamp(preTranslate - offset, -size, 0.0f);
314     } else {
315         translate = std::clamp(preTranslate + offset, 0.0f, size);
316     }
317     renderContext->UpdateTransformTranslate(TranslateOptions(0.0f, translate, 0.0f));
318     float opacity = renderContext->GetOpacityValue(1.0f);
319     opacity = std::clamp(opacity - offset / size, 0.0f, 1.0f);
320     renderContext->UpdateOpacity(opacity);
321     auto threshold = Dimension(TRANSLATE_THRESHOLD, DimensionUnit::VP).ConvertToPx();
322     if (Positive(offset) && LessNotEqual(std::abs(preTranslate), threshold) &&
323         GreatOrEqual(std::abs(translate), threshold)) {
324         StartHideTabBar();
325     } else if (Negative(offset) && LessNotEqual(size - std::abs(preTranslate), threshold) &&
326                GreatOrEqual(size - std::abs(translate), threshold)) {
327         StartShowTabBar();
328     }
329 }
330 
SetTabBarTranslate(const TranslateOptions & options)331 void TabBarPattern::SetTabBarTranslate(const TranslateOptions& options)
332 {
333     auto host = GetHost();
334     CHECK_NULL_VOID(host);
335     auto renderContext = host->GetRenderContext();
336     CHECK_NULL_VOID(renderContext);
337     renderContext->UpdateTransformTranslate(options);
338 }
339 
SetTabBarOpacity(float opacity)340 void TabBarPattern::SetTabBarOpacity(float opacity)
341 {
342     auto host = GetHost();
343     CHECK_NULL_VOID(host);
344     auto renderContext = host->GetRenderContext();
345     CHECK_NULL_VOID(renderContext);
346     renderContext->UpdateOpacity(opacity);
347 }
348 
FindTextAndImageNode(const RefPtr<FrameNode> & columnNode,RefPtr<FrameNode> & textNode,RefPtr<FrameNode> & imageNode)349 void FindTextAndImageNode(
350     const RefPtr<FrameNode>& columnNode, RefPtr<FrameNode>& textNode, RefPtr<FrameNode>& imageNode)
351 {
352     if (columnNode->GetTag() == V2::TEXT_ETS_TAG) {
353         textNode = columnNode;
354     } else if (columnNode->GetTag() == V2::IMAGE_ETS_TAG || columnNode->GetTag() == V2::SYMBOL_ETS_TAG) {
355         imageNode = columnNode;
356     } else {
357         std::list<RefPtr<UINode>> children = columnNode->GetChildren();
358         for (auto child : children) {
359             FindTextAndImageNode(AceType::DynamicCast<FrameNode>(child), textNode, imageNode);
360         }
361     }
362 }
363 
OnAttachToFrameNode()364 void TabBarPattern::OnAttachToFrameNode()
365 {
366     auto host = GetHost();
367     CHECK_NULL_VOID(host);
368     auto renderContext = host->GetRenderContext();
369     CHECK_NULL_VOID(renderContext);
370     renderContext->SetClipToFrame(true);
371     if (!host->GetLayoutProperty()->GetSafeAreaExpandOpts()) {
372         host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(
373             SafeAreaExpandOpts { .type = SAFE_AREA_TYPE_SYSTEM, .edges = SAFE_AREA_EDGE_BOTTOM });
374     }
375     InitSurfaceChangedCallback();
376 }
377 
SetTabBarFinishCallback()378 void TabBarPattern::SetTabBarFinishCallback()
379 {
380     CHECK_NULL_VOID(swiperController_);
381     swiperController_->SetTabBarFinishCallback([weak = WeakClaim(this)]() {
382         auto pattern = weak.Upgrade();
383         CHECK_NULL_VOID(pattern);
384         // always swipe with physical curve, ignore animationDuration
385         pattern->SetSwiperCurve(TabBarPhysicalCurve);
386 
387         if (pattern->scrollableEvent_) {
388             auto scrollable = pattern->scrollableEvent_->GetScrollable();
389             if (scrollable) {
390                 scrollable->StopScrollable();
391             }
392         }
393 
394         pattern->StopTranslateAnimation(true);
395         pattern->ResetIndicatorAnimationState();
396         auto swiperPattern = pattern->GetSwiperPattern();
397         CHECK_NULL_VOID(swiperPattern);
398         auto currentIndex = swiperPattern->GetCurrentIndex();
399         auto totalCount = swiperPattern->TotalCount();
400         if (currentIndex >= totalCount || currentIndex < 0) {
401             currentIndex = 0;
402         }
403         auto layoutProperty = pattern->GetLayoutProperty<TabBarLayoutProperty>();
404         CHECK_NULL_VOID(layoutProperty);
405         if (layoutProperty->GetIndicatorValue(0) != currentIndex) {
406             pattern->UpdateSubTabBoard(currentIndex);
407             pattern->UpdateTextColorAndFontWeight(currentIndex);
408             pattern->UpdateIndicator(currentIndex);
409             pattern->UpdatePaintIndicator(currentIndex, true);
410             pattern->SetChangeByClick(false);
411         }
412     });
413 }
414 
InitSurfaceChangedCallback()415 void TabBarPattern::InitSurfaceChangedCallback()
416 {
417     auto host = GetHost();
418     CHECK_NULL_VOID(host);
419     auto pipeline = host->GetContextRefPtr();
420     CHECK_NULL_VOID(pipeline);
421     if (!HasSurfaceChangedCallback()) {
422         auto callbackId = pipeline->RegisterSurfaceChangedCallback(
423             [weak = WeakClaim(this)](int32_t newWidth, int32_t newHeight, int32_t prevWidth, int32_t prevHeight,
424                 WindowSizeChangeReason type) {
425                 auto pattern = weak.Upgrade();
426                 if (!pattern) {
427                     return;
428                 }
429 
430                 pattern->windowSizeChangeReason_ = type;
431                 pattern->prevRootSize_ = std::make_pair(prevWidth, prevHeight);
432 
433                 if (type == WindowSizeChangeReason::ROTATION) {
434                     pattern->StopTranslateAnimation();
435                 }
436             });
437         UpdateSurfaceChangedCallbackId(callbackId);
438     }
439 }
440 
OnDetachFromFrameNode(FrameNode * node)441 void TabBarPattern::OnDetachFromFrameNode(FrameNode* node)
442 {
443     auto pipeline = GetContext();
444     CHECK_NULL_VOID(pipeline);
445     if (HasSurfaceChangedCallback()) {
446         pipeline->UnregisterSurfaceChangedCallback(surfaceChangedCallbackId_.value_or(-1));
447     }
448     pipeline->RemoveWindowStateChangedCallback(node->GetId());
449 }
450 
BeforeCreateLayoutWrapper()451 void TabBarPattern::BeforeCreateLayoutWrapper()
452 {
453     auto host = GetHost();
454     CHECK_NULL_VOID(host);
455     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
456     CHECK_NULL_VOID(layoutProperty);
457     if (targetIndex_) {
458         targetIndex_ = GetLoopIndex(targetIndex_.value());
459     }
460     if (isExecuteBuilder_) {
461         jumpIndex_ = layoutProperty->GetIndicatorValue(0);
462         isExecuteBuilder_ = false;
463     }
464 }
465 
AddTabBarItemClickAndTouchEvent(const RefPtr<FrameNode> & tabBarItem)466 void TabBarPattern::AddTabBarItemClickAndTouchEvent(const RefPtr<FrameNode>& tabBarItem)
467 {
468     CHECK_NULL_VOID(tabBarItem);
469     auto tabBarItemId = tabBarItem->GetId();
470     if (clickEvents_.find(tabBarItemId) != clickEvents_.end()) {
471         return;
472     }
473     auto eventHub = tabBarItem->GetEventHub<EventHub>();
474     CHECK_NULL_VOID(eventHub);
475     auto gestureHub = eventHub->GetOrCreateGestureEventHub();
476     CHECK_NULL_VOID(gestureHub);
477     auto clickCallback = [weak = WeakClaim(this), tabBarItemId](GestureEvent& info) {
478         auto tabBar = weak.Upgrade();
479         CHECK_NULL_VOID(tabBar);
480         auto host = tabBar->GetHost();
481         CHECK_NULL_VOID(host);
482         auto index = host->GetChildFlatIndex(tabBarItemId).second;
483         tabBar->HandleClick(info.GetSourceDevice(), index);
484     };
485     auto clickEvent = AceType::MakeRefPtr<ClickEvent>(std::move(clickCallback));
486     clickEvents_[tabBarItemId] = clickEvent;
487     gestureHub->AddClickEvent(clickEvent);
488 
489     if (touchEvents_.find(tabBarItemId) != touchEvents_.end()) {
490         return;
491     }
492     auto touchCallback = [weak = WeakClaim(this), tabBarItemId](const TouchEventInfo& info) {
493         auto tabBar = weak.Upgrade();
494         CHECK_NULL_VOID(tabBar);
495         auto host = tabBar->GetHost();
496         CHECK_NULL_VOID(host);
497         auto index = host->GetChildFlatIndex(tabBarItemId).second;
498         for (auto touchInfo : info.GetTouches()) {
499             tabBar->HandleTouchEvent(touchInfo.GetTouchType(), index);
500         }
501     };
502     auto touchEvent = AceType::MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
503     touchEvents_[tabBarItemId] = touchEvent;
504     gestureHub->AddTouchEvent(touchEvent);
505 }
506 
AddTabBarItemCallBack(const RefPtr<FrameNode> & tabBarItem)507 void TabBarPattern::AddTabBarItemCallBack(const RefPtr<FrameNode>& tabBarItem)
508 {
509     CHECK_NULL_VOID(tabBarItem);
510     auto tabBarItemId = tabBarItem->GetId();
511     auto columnAccessibilityProperty = tabBarItem->GetAccessibilityProperty<AccessibilityProperty>();
512     CHECK_NULL_VOID(columnAccessibilityProperty);
513     columnAccessibilityProperty->SetOnAccessibilityFocusCallback([weak = WeakClaim(this), tabBarItemId](bool focus) {
514         if (focus) {
515             auto tabBar = weak.Upgrade();
516             CHECK_NULL_VOID(tabBar);
517             auto host = tabBar->GetHost();
518             CHECK_NULL_VOID(host);
519             auto index = host->GetChildFlatIndex(tabBarItemId).second;
520             tabBar->accessibilityFocusIndicator_ = index;
521             tabBar->FocusCurrentOffset(index);
522         }
523     });
524 }
525 
AddMaskItemClickEvent()526 void TabBarPattern::AddMaskItemClickEvent()
527 {
528     auto host = GetHost();
529     CHECK_NULL_VOID(host);
530     auto childCount = host->GetChildren().size() - MASK_COUNT;
531 
532     for (int32_t maskIndex = 0; maskIndex < MASK_COUNT; maskIndex++) {
533         auto maskNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(childCount + maskIndex));
534         CHECK_NULL_VOID(maskNode);
535         auto maskNodeId = maskNode->GetId();
536         if (clickEvents_.find(maskNodeId) != clickEvents_.end()) {
537             continue;
538         }
539 
540         auto eventHub = maskNode->GetEventHub<EventHub>();
541         CHECK_NULL_VOID(eventHub);
542         auto gestureHub = eventHub->GetOrCreateGestureEventHub();
543         CHECK_NULL_VOID(gestureHub);
544         auto clickCallback = [weak = WeakClaim(this), maskIndex](GestureEvent& info) {
545             auto tabBar = weak.Upgrade();
546             CHECK_NULL_VOID(tabBar);
547             auto layoutProperty = tabBar->GetLayoutProperty<TabBarLayoutProperty>();
548             CHECK_NULL_VOID(layoutProperty);
549             auto index = (maskIndex == 0) ? layoutProperty->GetSelectedMask().value_or(-1) :
550                 layoutProperty->GetUnselectedMask().value_or(-1);
551             if (index >= 0) {
552                 tabBar->HandleClick(info.GetSourceDevice(), index);
553             }
554         };
555         auto clickEvent = AceType::MakeRefPtr<ClickEvent>(std::move(clickCallback));
556         clickEvents_[maskNodeId] = clickEvent;
557         gestureHub->AddClickEvent(clickEvent);
558     }
559 }
560 
InitLongPressEvent(const RefPtr<GestureEventHub> & gestureHub)561 void TabBarPattern::InitLongPressEvent(const RefPtr<GestureEventHub>& gestureHub)
562 {
563     if (longPressEvent_) {
564         return;
565     }
566 
567     auto longPressTask = [weak = WeakClaim(this)](GestureEvent& info) {
568         auto tabBar = weak.Upgrade();
569         if (tabBar) {
570             tabBar->HandleLongPressEvent(info);
571         }
572     };
573     longPressEvent_ = AceType::MakeRefPtr<LongPressEvent>(std::move(longPressTask));
574     gestureHub->SetLongPressEvent(longPressEvent_);
575 }
576 
InitDragEvent(const RefPtr<GestureEventHub> & gestureHub)577 void TabBarPattern::InitDragEvent(const RefPtr<GestureEventHub>& gestureHub)
578 {
579     CHECK_NULL_VOID(!dragEvent_);
580     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
581         auto tabBar = weak.Upgrade();
582         CHECK_NULL_VOID(tabBar);
583         auto index = tabBar->CalculateSelectedIndex(info.GetLocalLocation());
584         auto host = tabBar->GetHost();
585         CHECK_NULL_VOID(host);
586         auto totalCount = host->TotalChildCount() - MASK_COUNT;
587         if (tabBar && tabBar->dialogNode_ && index >= 0 && index < totalCount) {
588             if (!tabBar->moveIndex_.has_value()) {
589                 tabBar->moveIndex_ = index;
590             }
591 
592             if (tabBar->moveIndex_ != index) {
593                 tabBar->CloseDialog();
594                 tabBar->moveIndex_ = index;
595                 tabBar->ShowDialogWithNode(index);
596             }
597         }
598     };
599     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
600         auto tabBar = weak.Upgrade();
601         CHECK_NULL_VOID(tabBar);
602         auto index = tabBar->CalculateSelectedIndex(info.GetLocalLocation());
603         if (tabBar->dialogNode_) {
604             tabBar->HandleClick(info.GetSourceDevice(), index);
605             tabBar->CloseDialog();
606         }
607     };
608     auto actionCancelTask = [weak = WeakClaim(this)] {
609         auto tabBar = weak.Upgrade();
610         CHECK_NULL_VOID(tabBar);
611         if (tabBar->dialogNode_) {
612             tabBar->CloseDialog();
613         }
614     };
615     dragEvent_ = MakeRefPtr<DragEvent>(
616         nullptr, std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
617     PanDirection panDirection = { .type = PanDirection::ALL };
618     gestureHub->SetDragEvent(dragEvent_, panDirection, DEFAULT_PAN_FINGER, DEFAULT_PAN_DISTANCE);
619 }
620 
InitScrollableEvent(const RefPtr<TabBarLayoutProperty> & layoutProperty,const RefPtr<GestureEventHub> & gestureHub)621 void TabBarPattern::InitScrollableEvent(
622     const RefPtr<TabBarLayoutProperty>& layoutProperty, const RefPtr<GestureEventHub>& gestureHub)
623 {
624     if (layoutProperty->GetTabBarModeValue(TabBarMode::FIXED) == TabBarMode::SCROLLABLE) {
625         InitScrollable(gestureHub);
626         SetEdgeEffect(gestureHub);
627     } else {
628         if (scrollableEvent_) {
629             gestureHub->RemoveScrollableEvent(scrollableEvent_);
630             scrollableEvent_.Reset();
631         }
632         if (scrollEffect_) {
633             gestureHub->RemoveScrollEdgeEffect(scrollEffect_);
634             scrollEffect_.Reset();
635         }
636     }
637 }
638 
InitScrollable(const RefPtr<GestureEventHub> & gestureHub)639 void TabBarPattern::InitScrollable(const RefPtr<GestureEventHub>& gestureHub)
640 {
641     auto host = GetHost();
642     CHECK_NULL_VOID(host);
643     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
644     CHECK_NULL_VOID(layoutProperty);
645     auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
646     if (axis_ == axis && scrollableEvent_) {
647         return;
648     }
649 
650     axis_ = axis;
651     auto task = [weak = WeakClaim(this)](double offset, int32_t source) {
652         if (source == SCROLL_FROM_START) {
653             return true;
654         }
655         auto pattern = weak.Upgrade();
656         CHECK_NULL_RETURN(pattern, false);
657         if (!pattern->CanScroll()) {
658             return false;
659         }
660 
661         if (pattern->IsOutOfBoundary()) {
662             // over scroll in drag update from normal to over scroll or during over scroll.
663             auto scrollable = pattern->scrollableEvent_->GetScrollable();
664             if (scrollable) {
665                 scrollable->SetCanOverScroll(true);
666             }
667 
668             auto host = pattern->GetHost();
669             CHECK_NULL_RETURN(host, false);
670             auto overScrollInfo = pattern->GetOverScrollInfo(pattern->GetContentSize());
671             if (source == SCROLL_FROM_UPDATE) {
672                 // adjust offset.
673                 if (overScrollInfo.second != 0.0f) {
674                     pattern->canOverScroll_ = true;
675                     auto friction = CalculateFriction(std::abs(overScrollInfo.first) / overScrollInfo.second);
676                     pattern->UpdateCurrentOffset(static_cast<float>(offset * friction));
677                 }
678                 return true;
679             }
680         }
681         if (source != SCROLL_FROM_AXIS) {
682             pattern->canOverScroll_ = true;
683         }
684         pattern->UpdateCurrentOffset(static_cast<float>(offset));
685         return true;
686     };
687 
688     if (scrollableEvent_) {
689         gestureHub->RemoveScrollableEvent(scrollableEvent_);
690     }
691 
692     scrollableEvent_ = MakeRefPtr<ScrollableEvent>(axis);
693     auto scrollable = MakeRefPtr<Scrollable>(task, axis);
694     scrollable->SetNodeId(host->GetAccessibilityId());
695     scrollable->Initialize(host);
696     scrollable->SetMaxFlingVelocity(MAX_FLING_VELOCITY);
697     auto renderContext = host->GetRenderContext();
698     CHECK_NULL_VOID(renderContext);
699     auto springProperty = scrollable->GetSpringProperty();
700     renderContext->AttachNodeAnimatableProperty(springProperty);
701     auto frictionProperty = scrollable->GetFrictionProperty();
702     renderContext->AttachNodeAnimatableProperty(frictionProperty);
703     scrollableEvent_->SetScrollable(scrollable);
704     gestureHub->AddScrollableEvent(scrollableEvent_);
705     scrollableEvent_->GetScrollable()->SetEdgeEffect(EdgeEffect::SPRING);
706 }
707 
CanScroll() const708 bool TabBarPattern::CanScroll() const
709 {
710     auto host = GetHost();
711     CHECK_NULL_RETURN(host, false);
712     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
713     CHECK_NULL_RETURN(layoutProperty, false);
714     if (layoutProperty->GetTabBarModeValue(TabBarMode::FIXED) == TabBarMode::FIXED) {
715         return false;
716     }
717 
718     if (visibleItemPosition_.empty()) {
719         return false;
720     }
721     auto visibleItemStartIndex = visibleItemPosition_.begin()->first;
722     auto visibleItemEndIndex = visibleItemPosition_.rbegin()->first;
723     auto visibleItemStartPos = visibleItemPosition_.begin()->second.startPos;
724     auto visibleItemEndPos = visibleItemPosition_.rbegin()->second.endPos;
725     auto childCount = host->TotalChildCount() - MASK_COUNT;
726     auto contentMainSize = GetContentSize().MainSize(layoutProperty->GetAxis().value_or(Axis::HORIZONTAL));
727     return visibleItemStartIndex > 0 || LessNotEqual(visibleItemStartPos, scrollMargin_) ||
728         visibleItemEndIndex < (childCount - 1) || GreatNotEqual(visibleItemEndPos, contentMainSize - scrollMargin_);
729 }
730 
GetOverScrollInfo(const SizeF & size)731 std::pair<float, float> TabBarPattern::GetOverScrollInfo(const SizeF& size)
732 {
733     auto overScroll = 0.0f;
734     auto mainSize = 0.0f;
735     if (visibleItemPosition_.empty()) {
736         return std::make_pair(overScroll, mainSize);
737     }
738 
739     auto visibleItemStartPos = visibleItemPosition_.begin()->second.startPos;
740     auto visibleItemEndPos = visibleItemPosition_.rbegin()->second.endPos;
741     auto startPos = visibleItemStartPos - scrollMargin_;
742     mainSize = size.MainSize(axis_);
743     if (Positive(startPos)) {
744         overScroll = startPos;
745     } else {
746         overScroll = mainSize - visibleItemEndPos - scrollMargin_;
747     }
748     return std::make_pair(overScroll, mainSize);
749 }
750 
InsideTabBarRegion(const TouchLocationInfo & locationInfo)751 bool TabBarPattern::InsideTabBarRegion(const TouchLocationInfo& locationInfo)
752 {
753     auto host = GetHost();
754     CHECK_NULL_RETURN(host, false);
755     auto geometryNode = host->GetGeometryNode();
756     CHECK_NULL_RETURN(geometryNode, false);
757     auto hotRegion = geometryNode->GetFrameRect();
758     auto touchPoint = PointF(static_cast<float>(locationInfo.GetLocalLocation().GetX()),
759         static_cast<float>(locationInfo.GetLocalLocation().GetY()));
760     return hotRegion.IsInRegion(touchPoint);
761 }
762 
InitHoverEvent()763 void TabBarPattern::InitHoverEvent()
764 {
765     if (hoverEvent_) {
766         return;
767     }
768     auto host = GetHost();
769     CHECK_NULL_VOID(host);
770     auto eventHub = GetHost()->GetEventHub<EventHub>();
771     auto inputHub = eventHub->GetOrCreateInputEventHub();
772 
773     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
774         auto pattern = weak.Upgrade();
775         if (pattern) {
776             pattern->HandleHoverEvent(isHover);
777         }
778     };
779     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
780     inputHub->AddOnHoverEvent(hoverEvent_);
781 }
782 
InitMouseEvent()783 void TabBarPattern::InitMouseEvent()
784 {
785     if (mouseEvent_) {
786         return;
787     }
788     auto host = GetHost();
789     CHECK_NULL_VOID(host);
790     auto eventHub = GetHost()->GetEventHub<EventHub>();
791     auto inputHub = eventHub->GetOrCreateInputEventHub();
792     auto mouseTask = [weak = WeakClaim(this)](const MouseInfo& info) {
793         auto pattern = weak.Upgrade();
794         if (pattern) {
795             pattern->HandleMouseEvent(info);
796         }
797     };
798     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
799     inputHub->AddOnMouseEvent(mouseEvent_);
800 }
801 
HandleMouseEvent(const MouseInfo & info)802 void TabBarPattern::HandleMouseEvent(const MouseInfo& info)
803 {
804     if (IsContainsBuilder()) {
805         return;
806     }
807     auto host = GetHost();
808     CHECK_NULL_VOID(host);
809     auto totalCount = host->TotalChildCount() - MASK_COUNT;
810     if (totalCount < 0) {
811         return;
812     }
813     auto index = CalculateSelectedIndex(info.GetLocalLocation());
814     if (index < 0 || index >= totalCount) {
815         if (hoverIndex_.has_value() && touchingIndex_.empty()) {
816             HandleMoveAway(hoverIndex_.value());
817         }
818         hoverIndex_.reset();
819         return;
820     }
821     auto mouseAction = info.GetAction();
822     if (mouseAction == MouseAction::MOVE || mouseAction == MouseAction::WINDOW_ENTER) {
823         if (!touchingIndex_.empty()) {
824             hoverIndex_ = index;
825             return;
826         }
827         if (!hoverIndex_.has_value()) {
828             HandleHoverOnEvent(index);
829             hoverIndex_ = index;
830             return;
831         }
832         if (hoverIndex_.value() != index) {
833             HandleMoveAway(hoverIndex_.value());
834             HandleHoverOnEvent(index);
835             hoverIndex_ = index;
836             return;
837         }
838         return;
839     }
840     if (mouseAction == MouseAction::WINDOW_LEAVE) {
841         if (hoverIndex_.has_value()) {
842             HandleMoveAway(hoverIndex_.value());
843         }
844     }
845 }
846 
HandleHoverEvent(bool isHover)847 void TabBarPattern::HandleHoverEvent(bool isHover)
848 {
849     if (IsContainsBuilder()) {
850         return;
851     }
852     isHover_ = isHover;
853     if (!isHover_ && hoverIndex_.has_value()) {
854         if (touchingIndex_.empty()) {
855             HandleMoveAway(hoverIndex_.value());
856         }
857         hoverIndex_.reset();
858     }
859 }
860 
HandleHoverOnEvent(int32_t index)861 void TabBarPattern::HandleHoverOnEvent(int32_t index)
862 {
863     auto pipelineContext = GetContext();
864     CHECK_NULL_VOID(pipelineContext);
865     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
866     CHECK_NULL_VOID(tabTheme);
867     PlayPressAnimation(index, GetSubTabBarHoverColor(index), AnimationType::HOVER);
868 }
869 
HandleMoveAway(int32_t index)870 void TabBarPattern::HandleMoveAway(int32_t index)
871 {
872     Color tabBarItemColor = Color::TRANSPARENT;
873     if (tabBarStyle_ == TabBarStyle::SUBTABBATSTYLE && isTabBarFocusActive_ && index == focusIndicator_) {
874         tabBarItemColor = tabBarItemFocusBgColor_;
875     }
876     PlayPressAnimation(index, tabBarItemColor, AnimationType::HOVER);
877 }
878 
GetCurrentFocusNode()879 RefPtr<FocusHub> TabBarPattern::GetCurrentFocusNode()
880 {
881     auto host = GetHost();
882     CHECK_NULL_RETURN(host, nullptr);
883     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
884     CHECK_NULL_RETURN(layoutProperty, nullptr);
885     auto indicator = layoutProperty->GetIndicatorValue(0);
886     if (tabBarStyle_ == TabBarStyle::BOTTOMTABBATSTYLE || tabBarStyle_ == TabBarStyle::SUBTABBATSTYLE) {
887         focusIndicator_ = indicator;
888     }
889     auto childNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(indicator));
890     CHECK_NULL_RETURN(childNode, nullptr);
891     auto childFocusHub = childNode->GetFocusHub();
892     CHECK_NULL_RETURN(childFocusHub, nullptr);
893     childFocusHub->SetFocusDependence(FocusDependence::SELF);
894     return childFocusHub;
895 }
896 
GetScopeFocusAlgorithm()897 ScopeFocusAlgorithm TabBarPattern::GetScopeFocusAlgorithm()
898 {
899     return ScopeFocusAlgorithm(axis_ == Axis::VERTICAL, isRTL_, ScopeType::FLEX,
900         [weak = WeakClaim(this)](
901             FocusStep step, const WeakPtr<FocusHub>& currentFocusHub, WeakPtr<FocusHub>& nextFocusHub) -> bool {
902             auto pattern = weak.Upgrade();
903             CHECK_NULL_RETURN(pattern, false);
904             nextFocusHub = pattern->GetNextFocusNode(step);
905             if (nextFocusHub.Upgrade()) {
906                 return true;
907             } else {
908                 return false;
909             }
910         });
911 }
912 
GetNextFocusNode(FocusStep step)913 WeakPtr<FocusHub> TabBarPattern::GetNextFocusNode(FocusStep step)
914 {
915     auto pipeline = GetContext();
916     CHECK_NULL_RETURN(pipeline, nullptr);
917     if (!pipeline->GetIsFocusActive()) {
918         return nullptr;
919     }
920     auto host = GetHost();
921     CHECK_NULL_RETURN(host, nullptr);
922     auto tabTheme = pipeline->GetTheme<TabTheme>();
923     CHECK_NULL_RETURN(tabTheme, nullptr);
924     auto indicator = 0;
925     if (tabBarStyle_ == TabBarStyle::BOTTOMTABBATSTYLE ||
926         (tabBarStyle_ == TabBarStyle::SUBTABBATSTYLE && !tabTheme->GetIsChangeFocusTextStyle())) {
927         indicator = focusIndicator_;
928         auto nextFocusIndicator = GetNextFocusIndicator(indicator, step);
929         if (nextFocusIndicator.has_value()) {
930             if (ContentWillChange(nextFocusIndicator.value())) {
931                 indicator = nextFocusIndicator.value();
932                 focusIndicator_ = indicator;
933                 FocusCurrentOffset(indicator);
934             }
935         } else {
936             return nullptr;
937         }
938     } else {
939         CHECK_NULL_RETURN(swiperController_, nullptr);
940         swiperController_->FinishAnimation();
941         auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
942         CHECK_NULL_RETURN(layoutProperty, nullptr);
943         indicator = layoutProperty->GetIndicatorValue(0);
944         auto nextFocusIndicator = GetNextFocusIndicator(indicator, step);
945         if (nextFocusIndicator.has_value()) {
946             if (ContentWillChange(indicator, nextFocusIndicator.value())) {
947                 indicator = nextFocusIndicator.value();
948                 focusIndicator_ = indicator;
949                 FocusIndexChange(indicator);
950             }
951         } else {
952             return nullptr;
953         }
954     }
955 
956     auto childNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(indicator));
957     CHECK_NULL_RETURN(childNode, nullptr);
958     auto childFocusHub = childNode->GetFocusHub();
959     CHECK_NULL_RETURN(childFocusHub, nullptr);
960     childFocusHub->SetFocusDependence(FocusDependence::SELF);
961     return AceType::WeakClaim(AceType::RawPtr(childFocusHub));
962 }
963 
GetNextFocusIndicator(int32_t indicator,FocusStep step)964 std::optional<int32_t> TabBarPattern::GetNextFocusIndicator(int32_t indicator, FocusStep step)
965 {
966     auto host = GetHost();
967     CHECK_NULL_RETURN(host, std::nullopt);
968     if (step == (axis_ == Axis::HORIZONTAL ? (isRTL_ ? FocusStep::RIGHT : FocusStep::LEFT) : FocusStep::UP) ||
969         step == FocusStep::SHIFT_TAB) {
970         if (indicator <= 0) {
971             return std::nullopt;
972         }
973         indicator -= 1;
974     } else if (step == (axis_ == Axis::HORIZONTAL ? (isRTL_ ? FocusStep::LEFT : FocusStep::RIGHT) : FocusStep::DOWN) ||
975         step == FocusStep::TAB) {
976         if (indicator >= host->TotalChildCount() - MASK_COUNT - 1) {
977             return std::nullopt;
978         }
979         indicator += 1;
980     } else if (step == (axis_ == Axis::HORIZONTAL ? FocusStep::LEFT_END : FocusStep::UP_END)) {
981         indicator = 0;
982     } else if (step == (axis_ == Axis::HORIZONTAL ? FocusStep::RIGHT_END : FocusStep::DOWN_END)) {
983         indicator = host->TotalChildCount() - MASK_COUNT - 1;
984     } else {
985         return std::nullopt;
986     }
987     return indicator;
988 }
989 
FocusIndexChange(int32_t index)990 void TabBarPattern::FocusIndexChange(int32_t index)
991 {
992     auto host = GetHost();
993     CHECK_NULL_VOID(host);
994     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
995     CHECK_NULL_VOID(tabsNode);
996     auto tabsPattern = tabsNode->GetPattern<TabsPattern>();
997     CHECK_NULL_VOID(tabsPattern);
998 
999     SetSwiperCurve(DurationCubicCurve);
1000     UpdateAnimationDuration();
1001     auto duration = GetAnimationDuration().value_or(0);
1002     if (tabsPattern->GetIsCustomAnimation()) {
1003         OnCustomContentTransition(indicator_, index);
1004     } else {
1005         if (duration > 0 && tabsPattern->GetAnimateMode() != TabAnimateMode::NO_ANIMATION) {
1006             tabContentWillChangeFlag_ = true;
1007             swiperController_->SwipeTo(index);
1008             animationTargetIndex_ = index;
1009         } else {
1010             swiperController_->SwipeToWithoutAnimation(index);
1011         }
1012     }
1013 
1014     UpdateIndicator(index);
1015     changeByClick_ = true;
1016     clickRepeat_ = true;
1017     UpdateTextColorAndFontWeight(index);
1018     UpdateSubTabBoard(index);
1019     if (duration > 0 && CanScroll()) {
1020         targetIndex_ = index;
1021     } else {
1022         jumpIndex_ = index;
1023     }
1024     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1025 }
1026 
FocusCurrentOffset(int32_t index)1027 void TabBarPattern::FocusCurrentOffset(int32_t index)
1028 {
1029     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
1030     CHECK_NULL_VOID(layoutProperty);
1031     auto barMode = layoutProperty->GetTabBarMode().value_or(TabBarMode::FIXED);
1032     auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
1033     auto tabBarNode = GetHost();
1034     CHECK_NULL_VOID(tabBarNode);
1035     auto mainSize = GetContentSize().MainSize(axis);
1036 
1037     if (barMode == TabBarMode::SCROLLABLE && !visibleItemPosition_.empty()) {
1038         auto iter = visibleItemPosition_.find(index);
1039         if (iter != visibleItemPosition_.end()) {
1040             auto startPos = iter->second.startPos;
1041             auto endPos = iter->second.endPos;
1042             if (GreatOrEqual(startPos, 0.0f) && LessOrEqual(endPos, mainSize)) {
1043                 return;
1044             }
1045         }
1046         focusIndex_ = index;
1047         tabBarNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1048     }
1049 }
1050 
OnModifyDone()1051 void TabBarPattern::OnModifyDone()
1052 {
1053     Pattern::OnModifyDone();
1054     auto host = GetHost();
1055     CHECK_NULL_VOID(host);
1056     auto hub = host->GetEventHub<EventHub>();
1057     CHECK_NULL_VOID(hub);
1058     auto gestureHub = hub->GetOrCreateGestureEventHub();
1059     CHECK_NULL_VOID(gestureHub);
1060 
1061     AddMaskItemClickEvent();
1062     InitTurnPageRateEvent();
1063     auto pipelineContext = GetContext();
1064     CHECK_NULL_VOID(pipelineContext);
1065     auto theme = pipelineContext->GetTheme<TabTheme>();
1066     CHECK_NULL_VOID(theme);
1067     InitTabBarProperties(theme);
1068     UpdateBackBlurStyle(theme);
1069 
1070     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
1071     CHECK_NULL_VOID(layoutProperty);
1072     InitScrollableEvent(layoutProperty, gestureHub);
1073     InitHoverEvent();
1074     InitMouseEvent();
1075     SetSurfaceChangeCallback();
1076     InitFocusEvent();
1077     SetAccessibilityAction();
1078     UpdateSubTabBoard(indicator_);
1079     UpdateTextColorAndFontWeight(indicator_);
1080     StopTranslateAnimation();
1081     StartShowTabBar();
1082     jumpIndex_ = layoutProperty->GetIndicatorValue(0);
1083 
1084     RemoveTabBarEventCallback();
1085     AddTabBarEventCallback();
1086     UpdateChildrenClipEdge();
1087 
1088     axis_ = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
1089     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
1090     CHECK_NULL_VOID(tabsNode);
1091     auto tabsLayoutProperty = AceType::DynamicCast<TabsLayoutProperty>(tabsNode->GetLayoutProperty());
1092     CHECK_NULL_VOID(tabsLayoutProperty);
1093     auto tabsDirection = tabsLayoutProperty->GetNonAutoLayoutDirection();
1094     auto tabBarDirection = layoutProperty->GetLayoutDirection();
1095     isRTL_ = tabBarDirection == TextDirection::RTL ||
1096              (tabBarDirection == TextDirection::AUTO && tabsDirection == TextDirection::RTL);
1097 }
1098 
ResetOnForceMeasure(int32_t index)1099 void TabBarPattern::ResetOnForceMeasure(int32_t index)
1100 {
1101     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
1102     CHECK_NULL_VOID(layoutProperty);
1103     if (layoutProperty->GetIndicatorValue(0) != index) {
1104         jumpIndex_ = index;
1105         focusIndicator_ = index;
1106         UpdateSubTabBoard(index);
1107         UpdateTextColorAndFontWeight(index);
1108         UpdateIndicator(index);
1109         UpdatePaintIndicator(index, true);
1110         HandleBottomTabBarChange(index);
1111     }
1112 }
1113 
UpdateBackBlurStyle(const RefPtr<TabTheme> & tabTheme)1114 void TabBarPattern::UpdateBackBlurStyle(const RefPtr<TabTheme>& tabTheme)
1115 {
1116     auto host = GetHost();
1117     CHECK_NULL_VOID(host);
1118     auto pipelineContext = GetContext();
1119     CHECK_NULL_VOID(pipelineContext);
1120     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1121         auto renderContext = host->GetRenderContext();
1122         CHECK_NULL_VOID(renderContext);
1123         auto defaultBlurStyle = static_cast<BlurStyle>(tabTheme->GetBottomTabBackgroundBlurStyle());
1124         if (defaultBlurStyle != BlurStyle::NO_MATERIAL && !renderContext->GetBackBlurStyle().has_value() &&
1125             !renderContext->GetBackBlurRadius().has_value() && !renderContext->GetBackgroundEffect().has_value()) {
1126             BlurStyleOption styleOption;
1127             styleOption.blurStyle = defaultBlurStyle;
1128             pipelineContext->RemoveWindowFocusChangedCallback(host->GetId());
1129             renderContext->UpdateBackBlurStyle(styleOption);
1130         }
1131     }
1132 }
1133 
SetSurfaceChangeCallback()1134 void TabBarPattern::SetSurfaceChangeCallback()
1135 {
1136     CHECK_NULL_VOID(swiperController_);
1137     auto surfaceChangeCallback = [weak = WeakClaim(this)]() {
1138         auto tabBarPattern = weak.Upgrade();
1139         CHECK_NULL_VOID(tabBarPattern);
1140         tabBarPattern->isTouchingSwiper_ = false;
1141     };
1142     swiperController_->SetSurfaceChangeCallback(std::move(surfaceChangeCallback));
1143 }
1144 
RemoveTabBarEventCallback()1145 void TabBarPattern::RemoveTabBarEventCallback()
1146 {
1147     CHECK_NULL_VOID(swiperController_);
1148     auto removeEventCallback = [weak = WeakClaim(this)]() {
1149         auto tabBarPattern = weak.Upgrade();
1150         CHECK_NULL_VOID(tabBarPattern);
1151         auto host = tabBarPattern->GetHost();
1152         CHECK_NULL_VOID(host);
1153         auto hub = host->GetEventHub<EventHub>();
1154         CHECK_NULL_VOID(hub);
1155         auto gestureHub = hub->GetOrCreateGestureEventHub();
1156         CHECK_NULL_VOID(gestureHub);
1157         auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
1158         CHECK_NULL_VOID(layoutProperty);
1159         if (layoutProperty->GetTabBarModeValue(TabBarMode::FIXED) == TabBarMode::SCROLLABLE) {
1160             gestureHub->RemoveScrollableEvent(tabBarPattern->scrollableEvent_);
1161         }
1162         if (tabBarPattern->tabBarStyle_ == TabBarStyle::BOTTOMTABBATSTYLE) {
1163             gestureHub->RemoveDragEvent();
1164             gestureHub->SetLongPressEvent(nullptr);
1165             tabBarPattern->longPressEvent_ = nullptr;
1166             tabBarPattern->dragEvent_ = nullptr;
1167         }
1168         tabBarPattern->isTouchingSwiper_ = true;
1169         for (const auto& childNode : host->GetChildren()) {
1170             CHECK_NULL_VOID(childNode);
1171             auto frameNode = AceType::DynamicCast<FrameNode>(childNode);
1172             CHECK_NULL_VOID(frameNode);
1173             auto childHub = frameNode->GetEventHub<EventHub>();
1174             CHECK_NULL_VOID(childHub);
1175             auto childGestureHub = childHub->GetOrCreateGestureEventHub();
1176             CHECK_NULL_VOID(childGestureHub);
1177             auto clickIter = tabBarPattern->clickEvents_.find(frameNode->GetId());
1178             if (clickIter != tabBarPattern->clickEvents_.end()) {
1179                 childGestureHub->RemoveClickEvent(clickIter->second);
1180             }
1181             auto touchIter = tabBarPattern->touchEvents_.find(frameNode->GetId());
1182             if (touchIter != tabBarPattern->touchEvents_.end()) {
1183                 childGestureHub->RemoveTouchEvent(touchIter->second);
1184             }
1185         }
1186     };
1187     swiperController_->SetRemoveTabBarEventCallback(std::move(removeEventCallback));
1188 }
1189 
AddTabBarEventCallback()1190 void TabBarPattern::AddTabBarEventCallback()
1191 {
1192     CHECK_NULL_VOID(swiperController_);
1193     auto addEventCallback = [weak = WeakClaim(this)]() {
1194         auto tabBarPattern = weak.Upgrade();
1195         CHECK_NULL_VOID(tabBarPattern);
1196         auto host = tabBarPattern->GetHost();
1197         CHECK_NULL_VOID(host);
1198         auto hub = host->GetEventHub<EventHub>();
1199         CHECK_NULL_VOID(hub);
1200         auto gestureHub = hub->GetOrCreateGestureEventHub();
1201         CHECK_NULL_VOID(gestureHub);
1202         auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
1203         CHECK_NULL_VOID(layoutProperty);
1204         if (layoutProperty->GetTabBarModeValue(TabBarMode::FIXED) == TabBarMode::SCROLLABLE) {
1205             gestureHub->AddScrollableEvent(tabBarPattern->scrollableEvent_);
1206         }
1207         for (const auto& childNode : host->GetChildren()) {
1208             CHECK_NULL_VOID(childNode);
1209             auto frameNode = AceType::DynamicCast<FrameNode>(childNode);
1210             CHECK_NULL_VOID(frameNode);
1211             auto childHub = frameNode->GetEventHub<EventHub>();
1212             CHECK_NULL_VOID(childHub);
1213             auto childGestureHub = childHub->GetOrCreateGestureEventHub();
1214             CHECK_NULL_VOID(childGestureHub);
1215             auto clickIter = tabBarPattern->clickEvents_.find(frameNode->GetId());
1216             if (clickIter != tabBarPattern->clickEvents_.end()) {
1217                 childGestureHub->AddClickEvent(clickIter->second);
1218             }
1219             auto touchIter = tabBarPattern->touchEvents_.find(frameNode->GetId());
1220             if (touchIter != tabBarPattern->touchEvents_.end()) {
1221                 childGestureHub->AddTouchEvent(touchIter->second);
1222             }
1223         }
1224         tabBarPattern->InitLongPressAndDragEvent();
1225     };
1226     swiperController_->SetAddTabBarEventCallback(std::move(addEventCallback));
1227 }
1228 
UpdateChildrenClipEdge()1229 void TabBarPattern::UpdateChildrenClipEdge()
1230 {
1231     auto tabBarNode = GetHost();
1232     CHECK_NULL_VOID(tabBarNode);
1233     auto tabBarRenderContext = tabBarNode->GetRenderContext();
1234     CHECK_NULL_VOID(tabBarRenderContext);
1235     bool clipEdge = tabBarRenderContext->GetClipEdgeValue(true);
1236     auto pipeline = GetContext();
1237     CHECK_NULL_VOID(pipeline);
1238     auto tabTheme = pipeline->GetTheme<TabTheme>();
1239     CHECK_NULL_VOID(tabTheme);
1240     if (tabTheme->GetIsChangeFocusTextStyle()) {
1241         clipEdge = false;
1242     }
1243     if (clipEdge != clipEdge_) {
1244         int32_t totalCount = tabBarNode->TotalChildCount() - MASK_COUNT;
1245         for (int32_t index = 0; index < totalCount; index++) {
1246             auto childNode = AceType::DynamicCast<FrameNode>(tabBarNode->GetChildAtIndex(index));
1247             CHECK_NULL_VOID(childNode);
1248             auto renderContext = childNode->GetRenderContext();
1249             CHECK_NULL_VOID(renderContext);
1250             renderContext->UpdateClipEdge(clipEdge);
1251         }
1252         clipEdge_ = clipEdge;
1253     }
1254 }
1255 
UpdatePaintIndicator(int32_t indicator,bool needMarkDirty)1256 void TabBarPattern::UpdatePaintIndicator(int32_t indicator, bool needMarkDirty)
1257 {
1258     auto tabBarNode = GetHost();
1259     CHECK_NULL_VOID(tabBarNode);
1260     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
1261     CHECK_NULL_VOID(tabBarPattern);
1262     auto paintProperty = GetPaintProperty<TabBarPaintProperty>();
1263     if (indicator_ >= static_cast<int32_t>(tabBarStyles_.size()) ||
1264         indicator < 0 || indicator >= static_cast<int32_t>(tabBarStyles_.size())) {
1265         return;
1266     }
1267     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
1268     CHECK_NULL_VOID(layoutProperty);
1269     if (tabBarPattern->IsContainsBuilder() || layoutProperty->GetAxis() == Axis::VERTICAL ||
1270         tabBarStyles_[indicator] == TabBarStyle::BOTTOMTABBATSTYLE) {
1271         paintProperty->ResetIndicator();
1272 
1273         if (needMarkDirty) {
1274             tabBarNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1275         }
1276 
1277         return;
1278     }
1279 
1280     RectF rect = {};
1281     if (visibleItemPosition_.find(indicator) != visibleItemPosition_.end()) {
1282         rect = layoutProperty->GetIndicatorRect(indicator);
1283         paintProperty->UpdateIndicator(indicator);
1284     } else {
1285         paintProperty->ResetIndicator();
1286     }
1287     if (!isTouchingSwiper_ || tabBarStyles_[indicator] != TabBarStyle::SUBTABBATSTYLE) {
1288         currentIndicatorOffset_ = rect.GetX() + rect.Width() / 2;
1289 
1290         if (needMarkDirty) {
1291             tabBarNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1292         }
1293     }
1294 }
1295 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1296 bool TabBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
1297 {
1298     if (config.skipMeasure && config.skipLayout) {
1299         return false;
1300     }
1301     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
1302     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
1303     auto tabBarLayoutAlgorithm = DynamicCast<TabBarLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
1304     CHECK_NULL_RETURN(tabBarLayoutAlgorithm, false);
1305     currentDelta_ = 0.0f;
1306     canOverScroll_ = false;
1307     visibleItemPosition_ = tabBarLayoutAlgorithm->GetVisibleItemPosition();
1308     scrollMargin_ = tabBarLayoutAlgorithm->GetScrollMargin();
1309     jumpIndex_ = tabBarLayoutAlgorithm->GetJumpIndex();
1310     barGridMargin_ = tabBarLayoutAlgorithm->GetBarGridMargin();
1311     auto layoutProperty = DynamicCast<TabBarLayoutProperty>(dirty->GetLayoutProperty());
1312     auto host = GetHost();
1313     CHECK_NULL_RETURN(host, false);
1314     auto swiperPattern = GetSwiperPattern();
1315     CHECK_NULL_RETURN(swiperPattern, false);
1316     int32_t indicator = swiperPattern->IsInFastAnimation() ? indicator_ : swiperPattern->GetCurrentIndex();
1317     int32_t totalCount = swiperPattern->TotalCount();
1318     if (indicator > totalCount - 1 || indicator < 0) {
1319         indicator = 0;
1320     }
1321     if (totalCount == 0) {
1322         isTouchingSwiper_ = false;
1323     }
1324     auto pipelineContext = GetContext();
1325     CHECK_NULL_RETURN(pipelineContext, false);
1326     if (targetIndex_) {
1327         TriggerTranslateAnimation(indicator_, targetIndex_.value());
1328         targetIndex_.reset();
1329     }
1330 
1331     if (swiperPattern->IsUseCustomAnimation()) {
1332         UpdateSubTabBoard(indicator);
1333         UpdatePaintIndicator(indicator, false);
1334     }
1335     if ((!swiperPattern->IsUseCustomAnimation() || isFirstLayout_) && !isAnimating_ && !IsMaskAnimationExecuted()) {
1336         UpdateSubTabBoard(indicator);
1337         UpdatePaintIndicator(indicator, true);
1338     }
1339     isFirstLayout_ = false;
1340     if (focusIndex_) {
1341         focusIndex_.reset();
1342         host->OnAccessibilityEvent(AccessibilityEventType::SCROLL_END);
1343     }
1344     indicator_ = layoutProperty->GetIndicatorValue(0);
1345 
1346     if (windowSizeChangeReason_) {
1347         if (*windowSizeChangeReason_ == WindowSizeChangeReason::ROTATION && animationTargetIndex_.has_value() &&
1348             animationTargetIndex_ != indicator) {
1349             swiperController_->SwipeToWithoutAnimation(animationTargetIndex_.value());
1350             animationTargetIndex_.reset();
1351             windowSizeChangeReason_.reset();
1352         } else if (prevRootSize_.first != PipelineContext::GetCurrentRootWidth() ||
1353             prevRootSize_.second != PipelineContext::GetCurrentRootHeight()) {
1354             StopTranslateAnimation();
1355             jumpIndex_ = indicator_;
1356             focusIndicator_ = indicator_;
1357             UpdateSubTabBoard(indicator_);
1358             UpdateIndicator(indicator_);
1359             UpdatePaintIndicator(indicator_, true);
1360             windowSizeChangeReason_.reset();
1361             host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1362         }
1363     }
1364     UpdateGradientRegions(!swiperPattern->IsUseCustomAnimation());
1365     if (!swiperPattern->IsUseCustomAnimation() && isTouchingSwiper_ &&
1366         layoutProperty->GetTabBarModeValue(TabBarMode::FIXED) == TabBarMode::SCROLLABLE) {
1367         ApplyTurnPageRateToIndicator(turnPageRate_);
1368     }
1369     return false;
1370 }
1371 
CustomizeExpandSafeArea()1372 bool TabBarPattern::CustomizeExpandSafeArea()
1373 {
1374     auto host = GetHost();
1375     CHECK_NULL_RETURN(host, false);
1376     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
1377     CHECK_NULL_RETURN(tabsNode, false);
1378     auto tabLayoutProperty = AceType::DynamicCast<TabsLayoutProperty>(tabsNode->GetLayoutProperty());
1379     CHECK_NULL_RETURN(tabLayoutProperty, false);
1380     return tabLayoutProperty->GetSafeAreaPaddingProperty() ? true : false;
1381 }
1382 
OnSyncGeometryNode(const DirtySwapConfig & config)1383 void TabBarPattern::OnSyncGeometryNode(const DirtySwapConfig& config)
1384 {
1385     auto host = GetHost();
1386     CHECK_NULL_VOID(host);
1387     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
1388     CHECK_NULL_VOID(tabsNode);
1389     auto tabLayoutProperty = AceType::DynamicCast<TabsLayoutProperty>(tabsNode->GetLayoutProperty());
1390     CHECK_NULL_VOID(tabLayoutProperty);
1391     if (!tabLayoutProperty->GetSafeAreaPaddingProperty()) {
1392         return;
1393     }
1394     auto tabBarSize = host->GetGeometryNode()->GetMarginFrameSize();
1395     auto tabBarOffset = host->GetGeometryNode()->GetMarginFrameOffset();
1396     auto tabsExpandEdges = tabsNode->GetAccumulatedSafeAreaExpand();
1397     auto tabBarExpandEdges = host->GetAccumulatedSafeAreaExpand();
1398     auto tabBarRect = RectF(tabBarOffset.GetX(), tabBarOffset.GetY(), tabBarSize.Width(),
1399         tabBarSize.Height() + tabsExpandEdges.bottom.value_or(0) + tabBarExpandEdges.bottom.value_or(0));
1400     auto tabBarRenderContext = host->GetRenderContext();
1401     CHECK_NULL_VOID(tabBarRenderContext);
1402     tabBarRenderContext->UpdatePaintRect(tabBarRect);
1403 }
1404 
InitLongPressAndDragEvent()1405 void TabBarPattern::InitLongPressAndDragEvent()
1406 {
1407     auto host = GetHost();
1408     CHECK_NULL_VOID(host);
1409     auto hub = host->GetEventHub<EventHub>();
1410     CHECK_NULL_VOID(hub);
1411     auto gestureHub = hub->GetOrCreateGestureEventHub();
1412     CHECK_NULL_VOID(gestureHub);
1413     auto pipelineContext = GetContext();
1414     CHECK_NULL_VOID(pipelineContext);
1415     float scale = pipelineContext->GetFontScale();
1416 
1417     bigScale_ = AgingAdapationDialogUtil::GetDialogBigFontSizeScale();
1418     largeScale_ = AgingAdapationDialogUtil::GetDialogLargeFontSizeScale();
1419     maxScale_ = AgingAdapationDialogUtil::GetDialogMaxFontSizeScale();
1420 
1421     if (tabBarStyle_ == TabBarStyle::BOTTOMTABBATSTYLE) {
1422         if (scale >= bigScale_) {
1423             InitLongPressEvent(gestureHub);
1424             InitDragEvent(gestureHub);
1425         } else {
1426             gestureHub->RemoveDragEvent();
1427             gestureHub->SetLongPressEvent(nullptr);
1428             longPressEvent_ = nullptr;
1429             dragEvent_ = nullptr;
1430         }
1431     }
1432 }
1433 
HandleLongPressEvent(const GestureEvent & info)1434 void TabBarPattern::HandleLongPressEvent(const GestureEvent& info)
1435 {
1436     auto index = CalculateSelectedIndex(info.GetLocalLocation());
1437     HandleClick(info.GetSourceDevice(), index);
1438     ShowDialogWithNode(index);
1439 }
1440 
ShowDialogWithNode(int32_t index)1441 void TabBarPattern::ShowDialogWithNode(int32_t index)
1442 {
1443     auto tabBarNode = GetHost();
1444     CHECK_NULL_VOID(tabBarNode);
1445     auto columnNode = AceType::DynamicCast<FrameNode>(tabBarNode->GetChildAtIndex(index));
1446     CHECK_NULL_VOID(columnNode);
1447     RefPtr<FrameNode> imageNode = nullptr;
1448     RefPtr<FrameNode> textNode = nullptr;
1449     FindTextAndImageNode(columnNode, textNode, imageNode);
1450     CHECK_NULL_VOID(imageNode);
1451     CHECK_NULL_VOID(textNode);
1452 
1453     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1454     CHECK_NULL_VOID(textLayoutProperty);
1455     auto textValue = textLayoutProperty->GetContent();
1456     if (imageNode->GetTag() == V2::SYMBOL_ETS_TAG) {
1457         dialogNode_ = AgingAdapationDialogUtil::ShowLongPressDialog(textValue.value_or(u""), imageNode);
1458     } else {
1459         auto imageProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1460         CHECK_NULL_VOID(imageProperty);
1461         ImageSourceInfo imageSourceInfo = imageProperty->GetImageSourceInfoValue();
1462         dialogNode_ = AgingAdapationDialogUtil::ShowLongPressDialog(textValue.value_or(u""), imageSourceInfo);
1463     }
1464 }
1465 
CloseDialog()1466 void TabBarPattern::CloseDialog()
1467 {
1468     auto pipelineContext = GetContext();
1469     CHECK_NULL_VOID(pipelineContext);
1470     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
1471     CHECK_NULL_VOID(context);
1472     auto overlayManager = context->GetOverlayManager();
1473     CHECK_NULL_VOID(overlayManager);
1474     overlayManager->CloseDialog(dialogNode_);
1475     dialogNode_.Reset();
1476 }
1477 
HandleClick(SourceType type,int32_t index)1478 void TabBarPattern::HandleClick(SourceType type, int32_t index)
1479 {
1480     auto host = GetHost();
1481     CHECK_NULL_VOID(host);
1482     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
1483     CHECK_NULL_VOID(layoutProperty);
1484     if (layoutProperty->GetTabBarModeValue(TabBarMode::FIXED) == TabBarMode::SCROLLABLE && scrollableEvent_) {
1485         auto scrollable = scrollableEvent_->GetScrollable();
1486         if (scrollable) {
1487             if (IsOutOfBoundary()) {
1488                 return;
1489             }
1490             scrollable->StopScrollable();
1491         }
1492     }
1493 
1494     auto totalCount = host->TotalChildCount() - MASK_COUNT;
1495     if (totalCount < 0) {
1496         return;
1497     }
1498 
1499     TAG_LOGI(AceLogTag::ACE_TABS, "Clicked tabBarIndex: %{public}d", index);
1500     if (index < 0 || index >= totalCount || !swiperController_ ||
1501         indicator_ >= static_cast<int32_t>(tabBarStyles_.size()) ||
1502         index >= static_cast<int32_t>(tabBarStyles_.size())) {
1503         return;
1504     }
1505     SetSwiperCurve(DurationCubicCurve);
1506 
1507     TabBarClickEvent(index);
1508     if (!ContentWillChange(layoutProperty->GetIndicatorValue(0), index)) {
1509         return;
1510     }
1511     if (tabBarStyles_[indicator_] == TabBarStyle::SUBTABBATSTYLE &&
1512         tabBarStyles_[index] == TabBarStyle::SUBTABBATSTYLE &&
1513         layoutProperty->GetAxisValue(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
1514         HandleSubTabBarClick(layoutProperty, index);
1515         return;
1516     }
1517     ClickTo(host, index);
1518 }
1519 
ClickTo(const RefPtr<FrameNode> & host,int32_t index)1520 void TabBarPattern::ClickTo(const RefPtr<FrameNode>& host, int32_t index)
1521 {
1522     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
1523     CHECK_NULL_VOID(tabsNode);
1524     auto tabsPattern = tabsNode->GetPattern<TabsPattern>();
1525     CHECK_NULL_VOID(tabsPattern);
1526     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
1527     CHECK_NULL_VOID(layoutProperty);
1528     int32_t indicator = layoutProperty->GetIndicatorValue(0);
1529     if (!tabsPattern->GetIsCustomAnimation() && indicator == index) {
1530         return;
1531     }
1532     swiperController_->FinishAnimation();
1533     UpdateAnimationDuration();
1534     auto duration = GetAnimationDuration().value_or(0);
1535     if (tabsPattern->GetIsCustomAnimation()) {
1536         OnCustomContentTransition(indicator, index);
1537     } else {
1538         if (duration > 0 && tabsPattern->GetAnimateMode() != TabAnimateMode::NO_ANIMATION) {
1539             PerfMonitor::GetPerfMonitor()->Start(PerfConstants::APP_TAB_SWITCH, PerfActionType::LAST_UP, "");
1540             tabContentWillChangeFlag_ = true;
1541             swiperController_->SwipeTo(index);
1542             animationTargetIndex_ = index;
1543         } else {
1544             swiperController_->SwipeToWithoutAnimation(index);
1545         }
1546     }
1547 
1548     UpdateIndicator(index);
1549     changeByClick_ = true;
1550     clickRepeat_ = true;
1551     if (duration > 0 && CanScroll()) {
1552         targetIndex_ = index;
1553     } else {
1554         jumpIndex_ = index;
1555     }
1556     auto pipeline = GetContext();
1557     CHECK_NULL_VOID(pipeline);
1558     auto tabTheme = pipeline->GetTheme<TabTheme>();
1559     CHECK_NULL_VOID(tabTheme);
1560     if (tabTheme->GetIsChangeFocusTextStyle()) {
1561         focusIndicator_ = index;
1562     }
1563     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1564 }
1565 
HandleBottomTabBarChange(int32_t index)1566 void TabBarPattern::HandleBottomTabBarChange(int32_t index)
1567 {
1568     AnimationUtils::StopAnimation(maskAnimation_);
1569     auto preIndex = GetImageColorOnIndex().value_or(indicator_);
1570     if (preIndex == index) {
1571         return;
1572     }
1573     UpdateImageColor(index);
1574     UpdateSymbolStats(index, preIndex);
1575     if (preIndex < 0 || preIndex >= static_cast<int32_t>(tabBarStyles_.size()) ||
1576         index < 0 || index >= static_cast<int32_t>(tabBarStyles_.size())) {
1577         return;
1578     }
1579     if (preIndex != index && (tabBarStyles_[preIndex] == TabBarStyle::BOTTOMTABBATSTYLE ||
1580                                    tabBarStyles_[index] == TabBarStyle::BOTTOMTABBATSTYLE)) {
1581         auto host = GetHost();
1582         CHECK_NULL_VOID(host);
1583         auto childCount = host->TotalChildCount() - MASK_COUNT;
1584         int32_t selectedIndex = -1;
1585         int32_t unselectedIndex = -1;
1586         if (preIndex < childCount && tabBarStyles_[preIndex] == TabBarStyle::BOTTOMTABBATSTYLE && CheckSvg(preIndex)) {
1587             unselectedIndex = preIndex;
1588         }
1589         if (index < childCount && tabBarStyles_[index] == TabBarStyle::BOTTOMTABBATSTYLE && CheckSvg(index)) {
1590             selectedIndex = index;
1591         }
1592         HandleBottomTabBarClick(selectedIndex, unselectedIndex);
1593     }
1594 }
1595 
CheckSvg(int32_t index) const1596 bool TabBarPattern::CheckSvg(int32_t index) const
1597 {
1598     auto host = GetHost();
1599     CHECK_NULL_RETURN(host, false);
1600     auto columnNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(index));
1601     CHECK_NULL_RETURN(columnNode && !columnNode->GetChildren().empty(), false);
1602     auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
1603     CHECK_NULL_RETURN(imageNode, false);
1604     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1605     CHECK_NULL_RETURN(imageLayoutProperty, false);
1606     ImageSourceInfo info;
1607     auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(info);
1608     return imageSourceInfo.IsSvg();
1609 }
1610 
HandleBottomTabBarClick(int32_t selectedIndex,int32_t unselectedIndex)1611 void TabBarPattern::HandleBottomTabBarClick(int32_t selectedIndex, int32_t unselectedIndex)
1612 {
1613     auto host = GetHost();
1614     CHECK_NULL_VOID(host);
1615     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
1616     CHECK_NULL_VOID(layoutProperty);
1617 
1618     std::vector<int32_t> selectedIndexes = {selectedIndex, unselectedIndex};
1619     OffsetF originalSelectedMaskOffset, originalUnselectedMaskOffset;
1620     float selectedImageSize = 0.0f, unselectedImageSize = 0.0f;
1621     for (int32_t maskIndex = 0; maskIndex < MASK_COUNT; maskIndex++) {
1622         if (maskIndex == 0) {
1623             layoutProperty->UpdateSelectedMask(selectedIndex);
1624         } else {
1625             layoutProperty->UpdateUnselectedMask(unselectedIndex);
1626         }
1627         if (selectedIndexes[maskIndex] < 0) {
1628             continue;
1629         }
1630         GetBottomTabBarImageSizeAndOffset(selectedIndexes, maskIndex, selectedImageSize, unselectedImageSize,
1631             originalSelectedMaskOffset, originalUnselectedMaskOffset);
1632     }
1633     ChangeMask(selectedIndex, selectedImageSize, originalSelectedMaskOffset, NO_OPACITY, HALF_MASK_RADIUS_RATIO, true);
1634     ChangeMask(unselectedIndex, unselectedImageSize, originalUnselectedMaskOffset, FULL_OPACITY,
1635         FULL_MASK_RADIUS_RATIO, false);
1636 
1637     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1638     PlayMaskAnimation(selectedImageSize, originalSelectedMaskOffset, selectedIndex, unselectedImageSize,
1639         originalUnselectedMaskOffset, unselectedIndex);
1640 }
1641 
GetBottomTabBarImageSizeAndOffset(const std::vector<int32_t> & selectedIndexes,int32_t maskIndex,float & selectedImageSize,float & unselectedImageSize,OffsetF & originalSelectedMaskOffset,OffsetF & originalUnselectedMaskOffset)1642 void TabBarPattern::GetBottomTabBarImageSizeAndOffset(const std::vector<int32_t>& selectedIndexes, int32_t maskIndex,
1643     float& selectedImageSize, float& unselectedImageSize, OffsetF& originalSelectedMaskOffset,
1644     OffsetF& originalUnselectedMaskOffset)
1645 {
1646     auto pipelineContext = GetContext();
1647     CHECK_NULL_VOID(pipelineContext);
1648     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
1649     CHECK_NULL_VOID(tabTheme);
1650 
1651     auto host = GetHost();
1652     CHECK_NULL_VOID(host);
1653     auto columnNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(selectedIndexes[maskIndex]));
1654     CHECK_NULL_VOID(columnNode && !columnNode->GetChildren().empty());
1655     auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
1656     CHECK_NULL_VOID(imageNode);
1657     auto imageGeometryNode = imageNode->GetGeometryNode();
1658     CHECK_NULL_VOID(imageGeometryNode);
1659     auto imageOffset = imageGeometryNode->GetFrameOffset();
1660     auto imageSize = imageGeometryNode->GetFrameSize().Width();
1661     if (maskIndex == 0) {
1662         selectedImageSize = imageSize;
1663     } else {
1664         unselectedImageSize = imageSize;
1665     }
1666     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1667     CHECK_NULL_VOID(imageLayoutProperty);
1668     ImageSourceInfo info;
1669     auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(info);
1670 
1671     auto maskPosition = host->GetChildren().size() - MASK_COUNT;
1672     if (maskPosition < 0) {
1673         return;
1674     }
1675     auto selectedMaskNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(maskPosition + maskIndex));
1676     CHECK_NULL_VOID(selectedMaskNode);
1677     selectedMaskNode->GetLayoutProperty()->UpdateLayoutDirection(TextDirection::LTR);
1678     if (maskIndex == 0) {
1679         originalSelectedMaskOffset = imageOffset;
1680     } else {
1681         originalUnselectedMaskOffset = imageOffset;
1682     }
1683     CHECK_NULL_VOID(!selectedMaskNode->GetChildren().empty());
1684     auto selectedImageNode = AceType::DynamicCast<FrameNode>(selectedMaskNode->GetChildren().front());
1685     CHECK_NULL_VOID(selectedImageNode);
1686 
1687     auto selectedImageLayoutProperty = selectedImageNode->GetLayoutProperty<ImageLayoutProperty>();
1688     CHECK_NULL_VOID(selectedImageLayoutProperty);
1689     UpdateBottomTabBarImageColor(selectedIndexes, maskIndex);
1690     selectedImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
1691     imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
1692 
1693     selectedImageNode->MarkModifyDone();
1694     selectedImageNode->MarkDirtyNode();
1695     imageNode->MarkModifyDone();
1696     imageNode->MarkDirtyNode();
1697 }
1698 
UpdateBottomTabBarImageColor(const std::vector<int32_t> & selectedIndexes,int32_t maskIndex)1699 void TabBarPattern::UpdateBottomTabBarImageColor(const std::vector<int32_t>& selectedIndexes, int32_t maskIndex)
1700 {
1701     auto pipelineContext = GetContext();
1702     CHECK_NULL_VOID(pipelineContext);
1703     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
1704     CHECK_NULL_VOID(tabTheme);
1705 
1706     auto host = GetHost();
1707     CHECK_NULL_VOID(host);
1708     auto columnNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(selectedIndexes[maskIndex]));
1709     CHECK_NULL_VOID(columnNode && !columnNode->GetChildren().empty());
1710     auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
1711     CHECK_NULL_VOID(imageNode);
1712 
1713     auto maskPosition = host->GetChildren().size() - MASK_COUNT;
1714     if (maskPosition < 0) {
1715         return;
1716     }
1717     auto selectedMaskNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(maskPosition + maskIndex));
1718     CHECK_NULL_VOID(selectedMaskNode && !selectedMaskNode->GetChildren().empty());
1719     auto selectedImageNode = AceType::DynamicCast<FrameNode>(selectedMaskNode->GetChildren().front());
1720     CHECK_NULL_VOID(selectedImageNode);
1721 
1722     auto selectedImagePaintProperty = selectedImageNode->GetPaintProperty<ImageRenderProperty>();
1723     CHECK_NULL_VOID(selectedImagePaintProperty);
1724     auto unselectedImagePaintProperty = imageNode->GetPaintProperty<ImageRenderProperty>();
1725     CHECK_NULL_VOID(unselectedImagePaintProperty);
1726     if (selectedIndexes[maskIndex] >= 0 && selectedIndexes[maskIndex] < static_cast<int32_t>(iconStyles_.size())) {
1727         if (iconStyles_[selectedIndexes[maskIndex]].selectedColor.has_value()) {
1728             selectedImagePaintProperty->UpdateSvgFillColor(
1729                 iconStyles_[selectedIndexes[maskIndex]].selectedColor.value());
1730         } else {
1731             selectedImagePaintProperty->UpdateSvgFillColor(tabTheme->GetBottomTabIconOn());
1732         }
1733 
1734         if (iconStyles_[selectedIndexes[maskIndex]].unselectedColor.has_value()) {
1735             unselectedImagePaintProperty->UpdateSvgFillColor(
1736                 iconStyles_[selectedIndexes[maskIndex]].unselectedColor.value());
1737         } else {
1738             unselectedImagePaintProperty->UpdateSvgFillColor(tabTheme->GetBottomTabIconOff());
1739         }
1740     }
1741 }
1742 
PlayMaskAnimation(float selectedImageSize,const OffsetF & originalSelectedMaskOffset,int32_t selectedIndex,float unselectedImageSize,const OffsetF & originalUnselectedMaskOffset,int32_t unselectedIndex)1743 void TabBarPattern::PlayMaskAnimation(float selectedImageSize,
1744     const OffsetF& originalSelectedMaskOffset, int32_t selectedIndex, float unselectedImageSize,
1745     const OffsetF& originalUnselectedMaskOffset, int32_t unselectedIndex)
1746 {
1747     auto curve = AceType::MakeRefPtr<CubicCurve>(0.4f, 0.0f, 0.2f, 1.0f);
1748     AnimationOption option;
1749     option.SetDuration(MASK_ANIMATION_DURATION);
1750     option.SetCurve(curve);
1751 
1752     maskAnimation_ = AnimationUtils::StartAnimation(
1753         option,
1754         [weak = AceType::WeakClaim(this), selectedIndex, unselectedIndex, selectedImageSize, originalSelectedMaskOffset,
1755             unselectedImageSize, originalUnselectedMaskOffset]() {
1756             AnimationUtils::AddKeyFrame(
1757                 HALF_PROGRESS, [weak, selectedIndex, unselectedIndex, selectedImageSize, originalSelectedMaskOffset,
1758                                    unselectedImageSize, originalUnselectedMaskOffset]() {
1759                     auto tabBar = weak.Upgrade();
1760                     if (tabBar) {
1761                         tabBar->ChangeMask(selectedIndex, selectedImageSize, originalSelectedMaskOffset, FULL_OPACITY,
1762                             INVALID_RATIO, true);
1763                         tabBar->ChangeMask(unselectedIndex, unselectedImageSize, originalUnselectedMaskOffset,
1764                             NEAR_FULL_OPACITY, INVALID_RATIO, false);
1765                     }
1766                 });
1767             AnimationUtils::AddKeyFrame(
1768                 FULL_PROGRESS, [weak, selectedIndex, unselectedIndex, selectedImageSize, originalSelectedMaskOffset,
1769                                    unselectedImageSize, originalUnselectedMaskOffset]() {
1770                     auto tabBar = weak.Upgrade();
1771                     if (tabBar) {
1772                         tabBar->ChangeMask(selectedIndex, selectedImageSize, originalSelectedMaskOffset, FULL_OPACITY,
1773                             FULL_MASK_RADIUS_RATIO, true);
1774                         tabBar->ChangeMask(unselectedIndex, unselectedImageSize, originalUnselectedMaskOffset,
1775                             NO_OPACITY, HALF_MASK_RADIUS_RATIO, false);
1776                     }
1777                 });
1778         },
1779         [weak = AceType::WeakClaim(this), selectedIndex, unselectedIndex]() {
1780             auto tabBar = weak.Upgrade();
1781             if (tabBar) {
1782                 auto host = tabBar->GetHost();
1783                 CHECK_NULL_VOID(host);
1784                 MaskAnimationFinish(host, selectedIndex, true);
1785                 MaskAnimationFinish(host, unselectedIndex, false);
1786             }
1787         });
1788 }
1789 
MaskAnimationFinish(const RefPtr<FrameNode> & host,int32_t selectedIndex,bool isSelected)1790 void TabBarPattern::MaskAnimationFinish(const RefPtr<FrameNode>& host, int32_t selectedIndex,
1791     bool isSelected)
1792 {
1793     if (selectedIndex < 0) {
1794         return;
1795     }
1796     auto tabBarLayoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
1797     CHECK_NULL_VOID(tabBarLayoutProperty);
1798     if (isSelected) {
1799         tabBarLayoutProperty->UpdateSelectedMask(-1);
1800     } else {
1801         tabBarLayoutProperty->UpdateUnselectedMask(-1);
1802     }
1803 
1804     auto columnNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(selectedIndex));
1805     CHECK_NULL_VOID(columnNode && !columnNode->GetChildren().empty());
1806     auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
1807     CHECK_NULL_VOID(imageNode);
1808 
1809     auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
1810     CHECK_NULL_VOID(imageLayoutProperty);
1811     auto imagePaintProperty = imageNode->GetPaintProperty<ImageRenderProperty>();
1812     CHECK_NULL_VOID(imagePaintProperty);
1813     ImageSourceInfo info;
1814     auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(info);
1815 
1816     auto pipelineContext = host->GetContext();
1817     CHECK_NULL_VOID(pipelineContext);
1818     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
1819     CHECK_NULL_VOID(tabTheme);
1820     auto tabBarPattern = host->GetPattern<TabBarPattern>();
1821     CHECK_NULL_VOID(tabBarPattern);
1822     auto iconStyles = tabBarPattern->GetIconStyle();
1823     if (selectedIndex >= 0 && selectedIndex < static_cast<int32_t>(iconStyles.size())) {
1824         if (isSelected) {
1825             if (iconStyles[selectedIndex].selectedColor.has_value()) {
1826                 imagePaintProperty->UpdateSvgFillColor(iconStyles[selectedIndex].selectedColor.value());
1827             } else {
1828                 imagePaintProperty->UpdateSvgFillColor(tabTheme->GetBottomTabIconOn());
1829             }
1830         } else {
1831             if (iconStyles[selectedIndex].unselectedColor.has_value()) {
1832                 imagePaintProperty->UpdateSvgFillColor(iconStyles[selectedIndex].unselectedColor.value());
1833             } else {
1834                 imagePaintProperty->UpdateSvgFillColor(tabTheme->GetBottomTabIconOff());
1835             }
1836         }
1837     }
1838     imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
1839 
1840     host->MarkDirtyNode();
1841     imageNode->MarkModifyDone();
1842     imageNode->MarkDirtyNode();
1843 }
1844 
ChangeMask(int32_t index,float imageSize,const OffsetF & originalMaskOffset,float opacity,float radiusRatio,bool isSelected)1845 void TabBarPattern::ChangeMask(int32_t index, float imageSize, const OffsetF& originalMaskOffset, float opacity,
1846     float radiusRatio, bool isSelected)
1847 {
1848     auto host = GetHost();
1849     CHECK_NULL_VOID(host);
1850     auto maskPosition = host->GetChildren().size() - MASK_COUNT;
1851     if (index < 0 || NearZero(imageSize) || maskPosition < 0) {
1852         return;
1853     }
1854 
1855     auto maskNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(maskPosition + !isSelected));
1856     CHECK_NULL_VOID(maskNode && !maskNode->GetChildren().empty());
1857     auto maskImageNode = AceType::DynamicCast<FrameNode>(maskNode->GetChildren().front());
1858     CHECK_NULL_VOID(maskImageNode);
1859     auto maskImageRenderContext = maskImageNode->GetRenderContext();
1860     CHECK_NULL_VOID(maskImageRenderContext);
1861 
1862     if (NonNegative(radiusRatio)) {
1863         auto maskRenderContext = maskNode->GetRenderContext();
1864         CHECK_NULL_VOID(maskRenderContext);
1865         auto maskGeometryNode = maskNode->GetGeometryNode();
1866         CHECK_NULL_VOID(maskGeometryNode);
1867         auto tabBarNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(index));
1868         CHECK_NULL_VOID(tabBarNode);
1869         auto tabBarGeometryNode = tabBarNode->GetGeometryNode();
1870         CHECK_NULL_VOID(tabBarGeometryNode);
1871 
1872         OffsetF maskOffset = originalMaskOffset;
1873         maskOffset.AddX(-imageSize * radiusRatio);
1874         maskOffset.AddY(imageSize * (1.0f - radiusRatio));
1875         auto tabBarOffset = tabBarGeometryNode->GetMarginFrameOffset();
1876         maskGeometryNode->SetMarginFrameOffset(maskOffset + tabBarOffset);
1877         maskGeometryNode->SetFrameSize(SizeF(imageSize * radiusRatio * 2.0f, imageSize * radiusRatio * 2.0f));
1878         maskRenderContext->SavePaintRect();
1879         maskRenderContext->SyncGeometryProperties(nullptr);
1880         BorderRadiusProperty borderRadiusProperty;
1881         borderRadiusProperty.SetRadius(Dimension(imageSize * radiusRatio));
1882         maskRenderContext->UpdateBorderRadius(borderRadiusProperty);
1883         maskImageRenderContext->UpdateOffset(OffsetT<Dimension>(Dimension(imageSize * radiusRatio),
1884             Dimension(imageSize * (radiusRatio - 1.0f))));
1885         auto maskImageGeometryNode = maskImageNode->GetGeometryNode();
1886         CHECK_NULL_VOID(maskImageGeometryNode);
1887         maskImageGeometryNode->SetFrameSize(SizeF(imageSize, imageSize));
1888         auto maskImageProperty = maskImageNode->GetLayoutProperty<ImageLayoutProperty>();
1889         CHECK_NULL_VOID(maskImageProperty);
1890         maskImageProperty->UpdateUserDefinedIdealSize(
1891             CalcSize(NG::CalcLength(Dimension(imageSize)), NG::CalcLength(Dimension(imageSize))));
1892         maskImageRenderContext->SetVisible(false);
1893         maskImageRenderContext->SavePaintRect();
1894         maskImageRenderContext->SyncGeometryProperties(nullptr);
1895     }
1896     maskImageRenderContext->UpdateOpacity(opacity);
1897 }
1898 
HandleSubTabBarClick(const RefPtr<TabBarLayoutProperty> & layoutProperty,int32_t index)1899 void TabBarPattern::HandleSubTabBarClick(const RefPtr<TabBarLayoutProperty>& layoutProperty, int32_t index)
1900 {
1901     auto host = GetHost();
1902     CHECK_NULL_VOID(host);
1903     auto tabsFrameNode = AceType::DynamicCast<TabsNode>(host->GetParent());
1904     CHECK_NULL_VOID(tabsFrameNode);
1905     auto tabsPattern = tabsFrameNode->GetPattern<TabsPattern>();
1906     CHECK_NULL_VOID(tabsPattern);
1907     int32_t indicator = layoutProperty->GetIndicatorValue(0);
1908     if (!tabsPattern->GetIsCustomAnimation() && indicator == index) {
1909         return;
1910     }
1911     swiperController_->FinishAnimation();
1912     UpdateAnimationDuration();
1913     auto duration = GetAnimationDuration().value_or(0);
1914     if (tabsPattern->GetIsCustomAnimation()) {
1915         OnCustomContentTransition(indicator, index);
1916     } else {
1917         if (duration> 0 && tabsPattern->GetAnimateMode() != TabAnimateMode::NO_ANIMATION) {
1918             PerfMonitor::GetPerfMonitor()->Start(PerfConstants::APP_TAB_SWITCH, PerfActionType::LAST_UP, "");
1919             tabContentWillChangeFlag_ = true;
1920             swiperController_->SwipeTo(index);
1921         } else {
1922             swiperController_->SwipeToWithoutAnimation(index);
1923         }
1924     }
1925 
1926     UpdateIndicator(index);
1927     changeByClick_ = true;
1928     clickRepeat_ = true;
1929     if (duration > 0 && CanScroll()) {
1930         targetIndex_ = index;
1931     } else if (duration <= 0) {
1932         jumpIndex_ = index;
1933     } else {
1934         TriggerTranslateAnimation(indicator, index);
1935     }
1936     swiperStartIndex_ = indicator;
1937     animationTargetIndex_ = index;
1938     UpdateTextColorAndFontWeight(index);
1939     UpdateSubTabBoard(index);
1940     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1941 }
1942 
HandleTouchEvent(TouchType touchType,int32_t index)1943 void TabBarPattern::HandleTouchEvent(TouchType touchType, int32_t index)
1944 {
1945     auto host = GetHost();
1946     CHECK_NULL_VOID(host);
1947     auto totalCount = host->TotalChildCount() - MASK_COUNT;
1948     if (IsContainsBuilder() || totalCount < 0) {
1949         return;
1950     }
1951 
1952     if (touchType == TouchType::DOWN && index >= 0 && index < totalCount) {
1953         HandleTouchDown(index);
1954         touchingIndex_.insert(index);
1955         return;
1956     }
1957 
1958     if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
1959         HandleTouchUp(index);
1960         touchingIndex_.erase(index);
1961     }
1962 }
1963 
CalculateSelectedIndex(const Offset & info)1964 int32_t TabBarPattern::CalculateSelectedIndex(const Offset& info)
1965 {
1966     if (visibleItemPosition_.empty()) {
1967         return -1;
1968     }
1969     auto host = GetHost();
1970     CHECK_NULL_RETURN(host, -1);
1971     auto geometryNode = host->GetGeometryNode();
1972     CHECK_NULL_RETURN(geometryNode, -1);
1973     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
1974     CHECK_NULL_RETURN(layoutProperty, -1);
1975     auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
1976     auto mainSize = geometryNode->GetFrameSize().MainSize(axis);
1977     auto local = isRTL_ && axis == Axis::HORIZONTAL ? OffsetF(mainSize - info.GetX(), info.GetY())
1978                                                     : OffsetF(info.GetX(), info.GetY());
1979     auto leftPadding = GetLeftPadding();
1980     for (auto& iter : visibleItemPosition_) {
1981         if (GreatOrEqual(local.GetMainOffset(axis), iter.second.startPos + leftPadding) &&
1982             LessOrEqual(local.GetMainOffset(axis), iter.second.endPos + leftPadding)) {
1983             return iter.first;
1984         }
1985     }
1986     return -1;
1987 }
1988 
HandleTouchDown(int32_t index)1989 void TabBarPattern::HandleTouchDown(int32_t index)
1990 {
1991     const auto& removeSwiperEventCallback = swiperController_->GetRemoveSwiperEventCallback();
1992     if (removeSwiperEventCallback) {
1993         removeSwiperEventCallback();
1994     }
1995     auto pipelineContext = GetContext();
1996     CHECK_NULL_VOID(pipelineContext);
1997     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
1998     CHECK_NULL_VOID(tabTheme);
1999     PlayPressAnimation(index, tabTheme->GetSubTabBarPressedColor(), AnimationType::PRESS);
2000 }
2001 
HandleTouchUp(int32_t index)2002 void TabBarPattern::HandleTouchUp(int32_t index)
2003 {
2004     const auto& addSwiperEventCallback = swiperController_->GetAddSwiperEventCallback();
2005     if (addSwiperEventCallback) {
2006         addSwiperEventCallback();
2007     }
2008     auto pipelineContext = GetContext();
2009     CHECK_NULL_VOID(pipelineContext);
2010     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
2011     CHECK_NULL_VOID(tabTheme);
2012     if (hoverIndex_.value_or(-1) == index) {
2013         PlayPressAnimation(index, GetSubTabBarHoverColor(index), AnimationType::HOVERTOPRESS);
2014         return;
2015     }
2016     PlayPressAnimation(index, Color::TRANSPARENT, AnimationType::PRESS);
2017     if (hoverIndex_.has_value()) {
2018         PlayPressAnimation(hoverIndex_.value(), GetSubTabBarHoverColor(hoverIndex_.value()), AnimationType::HOVER);
2019     }
2020 }
2021 
PlayPressAnimation(int32_t index,const Color & pressColor,AnimationType animationType)2022 void TabBarPattern::PlayPressAnimation(int32_t index, const Color& pressColor, AnimationType animationType)
2023 {
2024     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TWELVE) &&
2025         tabBarStyle_ == TabBarStyle::BOTTOMTABBATSTYLE && animationType == AnimationType::PRESS) {
2026         return;
2027     }
2028     auto pipelineContext = GetContext();
2029     CHECK_NULL_VOID(pipelineContext);
2030     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
2031     CHECK_NULL_VOID(tabTheme);
2032     AnimationOption option = AnimationOption();
2033     option.SetDuration(animationType == AnimationType::HOVERTOPRESS
2034                            ? static_cast<int32_t>(tabTheme->GetSubTabBarHoverToPressDuration())
2035                            : static_cast<int32_t>(tabTheme->GetSubTabBarHoverDuration()));
2036     option.SetDelay(0);
2037     option.SetCurve(animationType == AnimationType::PRESS   ? DurationCubicCurve
2038                     : animationType == AnimationType::HOVER ? Curves::FRICTION
2039                                                             : Curves::SHARP);
2040     option.SetFillMode(FillMode::FORWARDS);
2041     Color color = pressColor;
2042     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
2043     CHECK_NULL_VOID(layoutProperty);
2044     if (index < 0 || index >= static_cast<int32_t>(tabBarStyles_.size()) ||
2045         index >= static_cast<int32_t>(selectedModes_.size()) ||
2046         index >= static_cast<int32_t>(indicatorStyles_.size())) {
2047         return;
2048     }
2049     if (color == Color::TRANSPARENT && tabBarStyles_[index] == TabBarStyle::SUBTABBATSTYLE && index == indicator_ &&
2050         selectedModes_[index] == SelectedMode::BOARD &&
2051         layoutProperty->GetAxis().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
2052         color = indicatorStyles_[index].color;
2053     }
2054     AnimationUtils::Animate(option, [weak = AceType::WeakClaim(this), selectedIndex = index, color = color]() {
2055         auto tabBar = weak.Upgrade();
2056         CHECK_NULL_VOID(tabBar);
2057         auto host = tabBar->GetHost();
2058         CHECK_NULL_VOID(host);
2059         auto columnNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(selectedIndex));
2060         CHECK_NULL_VOID(columnNode);
2061         auto renderContext = columnNode->GetRenderContext();
2062         CHECK_NULL_VOID(renderContext);
2063         if (selectedIndex < static_cast<int32_t>(tabBar->tabBarStyles_.size()) &&
2064             tabBar->tabBarStyles_[selectedIndex] != TabBarStyle::SUBTABBATSTYLE) {
2065             BorderRadiusProperty borderRadiusProperty;
2066             auto pipelineContext = host->GetContext();
2067             CHECK_NULL_VOID(pipelineContext);
2068             auto tabTheme = pipelineContext->GetTheme<TabTheme>();
2069             CHECK_NULL_VOID(tabTheme);
2070             borderRadiusProperty.SetRadius(tabTheme->GetFocusIndicatorRadius());
2071             renderContext->UpdateBorderRadius(borderRadiusProperty);
2072         }
2073         renderContext->UpdateBackgroundColor(color);
2074         columnNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2075     }, [weak = AceType::WeakClaim(this), selectedIndex = index]() {
2076         auto tabBar = weak.Upgrade();
2077         CHECK_NULL_VOID(tabBar);
2078         if (selectedIndex < static_cast<int32_t>(tabBar->tabBarStyles_.size()) &&
2079             tabBar->tabBarStyles_[selectedIndex] != TabBarStyle::SUBTABBATSTYLE) {
2080             auto host = tabBar->GetHost();
2081             CHECK_NULL_VOID(host);
2082             auto columnNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(selectedIndex));
2083             CHECK_NULL_VOID(columnNode);
2084             auto renderContext = columnNode->GetRenderContext();
2085             CHECK_NULL_VOID(renderContext);
2086             renderContext->ResetBorderRadius();
2087             columnNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2088         }
2089     });
2090 }
2091 
OnTabBarIndexChange(int32_t index)2092 void TabBarPattern::OnTabBarIndexChange(int32_t index)
2093 {
2094     auto pipeline = GetContext();
2095     CHECK_NULL_VOID(pipeline);
2096     pipeline->AddAfterRenderTask([weak = WeakClaim(this), index]() {
2097         auto tabBarPattern = weak.Upgrade();
2098         CHECK_NULL_VOID(tabBarPattern);
2099         auto tabBarNode = tabBarPattern->GetHost();
2100         CHECK_NULL_VOID(tabBarNode);
2101         auto tabBarLayoutProperty = tabBarPattern->GetLayoutProperty<TabBarLayoutProperty>();
2102         CHECK_NULL_VOID(tabBarLayoutProperty);
2103         if (!tabBarPattern->IsMaskAnimationByCreate()) {
2104             tabBarPattern->HandleBottomTabBarChange(index);
2105         }
2106         tabBarPattern->SetMaskAnimationByCreate(false);
2107         tabBarPattern->SetIndicator(index);
2108         tabBarPattern->UpdateSubTabBoard(index);
2109         tabBarPattern->UpdatePaintIndicator(index, true);
2110         tabBarPattern->UpdateTextColorAndFontWeight(index);
2111         if (!tabBarPattern->GetClickRepeat() || tabBarLayoutProperty->GetIndicator().value_or(0) == index) {
2112             tabBarPattern->ResetIndicatorAnimationState();
2113             tabBarPattern->UpdateIndicator(index);
2114         }
2115         tabBarPattern->isTouchingSwiper_ = false;
2116         tabBarPattern->SetClickRepeat(false);
2117         if (tabBarPattern->GetChangeByClick()) {
2118             tabBarPattern->SetChangeByClick(false);
2119             return;
2120         }
2121         if (tabBarLayoutProperty->GetTabBarMode().value_or(TabBarMode::FIXED) == TabBarMode::SCROLLABLE) {
2122             tabBarPattern->UpdateAnimationDuration();
2123             auto duration = tabBarPattern->GetAnimationDuration().value_or(0);
2124             if (duration > 0 && tabBarPattern->CanScroll()) {
2125                 tabBarPattern->StopTranslateAnimation();
2126                 tabBarPattern->targetIndex_ = index;
2127                 tabBarNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2128             } else {
2129                 tabBarPattern->StopTranslateAnimation();
2130                 tabBarPattern->jumpIndex_ = index;
2131                 tabBarNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2132             }
2133         }
2134     });
2135     pipeline->RequestFrame();
2136 }
2137 
UpdateCurrentOffset(float offset)2138 void TabBarPattern::UpdateCurrentOffset(float offset)
2139 {
2140     if (NearZero(offset)) {
2141         return;
2142     }
2143     auto host = GetHost();
2144     CHECK_NULL_VOID(host);
2145     currentDelta_ = offset;
2146     UpdateSubTabBoard(indicator_);
2147     UpdateIndicator(indicator_);
2148     UpdatePaintIndicator(indicator_, true);
2149     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2150 }
2151 
UpdateIndicator(int32_t indicator)2152 void TabBarPattern::UpdateIndicator(int32_t indicator)
2153 {
2154     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
2155     CHECK_NULL_VOID(layoutProperty);
2156     layoutProperty->UpdateIndicator(indicator);
2157     clickRepeat_ = false;
2158 
2159     auto host = GetHost();
2160     CHECK_NULL_VOID(host);
2161     auto focusHub = host->GetFocusHub();
2162     CHECK_NULL_VOID(focusHub);
2163     if (focusHub->IsCurrentFocus()) {
2164         return;
2165     }
2166     auto childFocusHub = GetCurrentFocusNode();
2167     CHECK_NULL_VOID(childFocusHub);
2168     focusHub->SetLastWeakFocusNode(AceType::WeakClaim(AceType::RawPtr(childFocusHub)));
2169 }
2170 
UpdateGradientRegions(bool needMarkDirty)2171 void TabBarPattern::UpdateGradientRegions(bool needMarkDirty)
2172 {
2173     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
2174     CHECK_NULL_VOID(layoutProperty);
2175     auto barMode = layoutProperty->GetTabBarMode().value_or(TabBarMode::FIXED);
2176     auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
2177     auto tabBarNode = GetHost();
2178     CHECK_NULL_VOID(tabBarNode);
2179     auto childCount = tabBarNode->TotalChildCount() - MASK_COUNT;
2180     auto mainSize = GetContentSize().MainSize(axis);
2181 
2182     std::fill(gradientRegions_.begin(), gradientRegions_.end(), false);
2183     if (barMode == TabBarMode::SCROLLABLE && !visibleItemPosition_.empty()) {
2184         auto visibleItemStartIndex = visibleItemPosition_.begin()->first;
2185         auto visibleItemEndIndex = visibleItemPosition_.rbegin()->first;
2186         auto visibleItemStartPos = visibleItemPosition_.begin()->second.startPos;
2187         auto visibleItemEndPos = visibleItemPosition_.rbegin()->second.endPos;
2188         if (visibleItemStartIndex > 0 || LessNotEqual(visibleItemStartPos, scrollMargin_)) {
2189             auto gradientIndex = axis == Axis::HORIZONTAL ? (isRTL_ ? RIGHT_GRADIENT : LEFT_GRADIENT)
2190                                                           : TOP_GRADIENT;
2191             gradientRegions_[gradientIndex] = true;
2192         }
2193         if (visibleItemEndIndex < childCount - 1 || GreatNotEqual(visibleItemEndPos + scrollMargin_, mainSize)) {
2194             auto gradientIndex = axis == Axis::HORIZONTAL ? (isRTL_ ? LEFT_GRADIENT : RIGHT_GRADIENT)
2195                                                           : BOTTOM_GRADIENT;
2196             gradientRegions_[gradientIndex] = true;
2197         }
2198     }
2199 
2200     if (needMarkDirty) {
2201         tabBarNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2202     }
2203 }
2204 
UpdateTextColorAndFontWeight(int32_t indicator)2205 void TabBarPattern::UpdateTextColorAndFontWeight(int32_t indicator)
2206 {
2207     auto tabBarNode = GetHost();
2208     CHECK_NULL_VOID(tabBarNode);
2209     auto columnNode = DynamicCast<FrameNode>(tabBarNode->GetChildAtIndex(indicator));
2210     CHECK_NULL_VOID(columnNode);
2211     int32_t selectedColumnId = 0;
2212     int32_t focusedColumnId = 0;
2213     GetColumnId(selectedColumnId, focusedColumnId, indicator);
2214     auto pipelineContext = GetContext();
2215     CHECK_NULL_VOID(pipelineContext);
2216     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
2217     CHECK_NULL_VOID(tabTheme);
2218     auto tabBarLayoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
2219     CHECK_NULL_VOID(tabBarLayoutProperty);
2220     auto axis = tabBarLayoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
2221     int32_t index = 0;
2222     for (const auto& columnNode : tabBarNode->GetChildren()) {
2223         CHECK_NULL_VOID(columnNode);
2224         auto columnId = columnNode->GetId();
2225         auto iter = tabBarType_.find(columnId);
2226         if (iter != tabBarType_.end() && iter->second != TabBarParamType::NORMAL) {
2227             index++;
2228             continue;
2229         }
2230         if (labelStyles_.find(columnId) == labelStyles_.end() || columnNode->GetChildren().empty()) {
2231             index++;
2232             continue;
2233         }
2234         auto textNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().back());
2235         CHECK_NULL_VOID(textNode);
2236         auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
2237         CHECK_NULL_VOID(textLayoutProperty);
2238         auto isSelected = columnId == selectedColumnId;
2239         if (isSelected) {
2240             UpdateSelectedTextColor(tabTheme, axis, textLayoutProperty, index, columnId);
2241         } else {
2242             textLayoutProperty->UpdateTextColor(
2243                 labelStyles_[columnId].unselectedColor.value_or(tabTheme->GetSubTabTextOffColor()));
2244         }
2245         UpdateSubTabFocusedTextColor(tabTheme, columnId == focusedColumnId, textLayoutProperty, index, isSelected);
2246         if (index < static_cast<int32_t>(tabBarStyles_.size()) && tabBarStyles_[index] == TabBarStyle::SUBTABBATSTYLE &&
2247             !labelStyles_[columnId].fontWeight.has_value()) {
2248             textLayoutProperty->UpdateFontWeight(isSelected ? FontWeight::MEDIUM : FontWeight::NORMAL);
2249         }
2250         textNode->MarkModifyDone();
2251         textNode->MarkDirtyNode();
2252         index++;
2253     }
2254 }
2255 
UpdateSelectedTextColor(const RefPtr<TabTheme> & tabTheme,OHOS::Ace::Axis axis,RefPtr<TextLayoutProperty> textLayoutProperty,int32_t index,int32_t columnId)2256 void TabBarPattern::UpdateSelectedTextColor(const RefPtr<TabTheme>& tabTheme, OHOS::Ace::Axis axis,
2257     RefPtr<TextLayoutProperty> textLayoutProperty, int32_t index, int32_t columnId)
2258 {
2259     auto selectedColor = index < static_cast<int32_t>(selectedModes_.size()) &&
2260                                  selectedModes_[index] == SelectedMode::BOARD && axis == Axis::HORIZONTAL
2261                              ? tabTheme->GetSubTabBoardTextOnColor()
2262                              : tabTheme->GetSubTabTextOnColor();
2263     textLayoutProperty->UpdateTextColor(labelStyles_[columnId].selectedColor.value_or(selectedColor));
2264 }
2265 
UpdateImageColor(int32_t indicator)2266 void TabBarPattern::UpdateImageColor(int32_t indicator)
2267 {
2268     auto tabBarNode = GetHost();
2269     CHECK_NULL_VOID(tabBarNode);
2270     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
2271     CHECK_NULL_VOID(tabBarPattern);
2272     if (tabBarPattern->IsContainsBuilder()) {
2273         return;
2274     }
2275     auto pipelineContext = GetContext();
2276     CHECK_NULL_VOID(pipelineContext);
2277     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
2278     CHECK_NULL_VOID(tabTheme);
2279     int32_t index = 0;
2280     for (const auto& columnNode : tabBarNode->GetChildren()) {
2281         CHECK_NULL_VOID(columnNode && !columnNode->GetChildren().empty());
2282         auto imageNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
2283         CHECK_NULL_VOID(imageNode);
2284         if (imageNode->GetTag() != V2::IMAGE_ETS_TAG) {
2285             index++;
2286             continue;
2287         }
2288         auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
2289         CHECK_NULL_VOID(imageLayoutProperty);
2290         auto imagePaintProperty = imageNode->GetPaintProperty<ImageRenderProperty>();
2291         CHECK_NULL_VOID(imagePaintProperty);
2292         ImageSourceInfo info;
2293         auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(info);
2294         if (index >= 0 && index < static_cast<int32_t>(iconStyles_.size())) {
2295             if (indicator == index) {
2296                 imagePaintProperty->UpdateSvgFillColor(iconStyles_[index].selectedColor.has_value() ?
2297                     iconStyles_[index].selectedColor.value() : tabTheme->GetBottomTabIconOn());
2298             } else {
2299                 imagePaintProperty->UpdateSvgFillColor(iconStyles_[index].unselectedColor.has_value() ?
2300                     iconStyles_[index].unselectedColor.value() : tabTheme->GetBottomTabIconOff());
2301             }
2302         }
2303         imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
2304         imageNode->MarkModifyDone();
2305         imageNode->MarkDirtyNode();
2306         index++;
2307     }
2308     SetImageColorOnIndex(indicator);
2309 }
2310 
UpdateSymbolStats(int32_t index,int32_t preIndex)2311 void TabBarPattern::UpdateSymbolStats(int32_t index, int32_t preIndex)
2312 {
2313     auto tabBarNode = GetHost();
2314     CHECK_NULL_VOID(tabBarNode);
2315     auto tabBarPattern = tabBarNode->GetPattern<TabBarPattern>();
2316     CHECK_NULL_VOID(tabBarPattern);
2317     auto pipelineContext = GetContext();
2318     CHECK_NULL_VOID(pipelineContext);
2319     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
2320     CHECK_NULL_VOID(tabTheme);
2321     if (tabBarPattern->IsContainsBuilder()) {
2322         return;
2323     }
2324     std::vector<int32_t> indexes = {index, preIndex};
2325     for (uint32_t i = 0; i < indexes.size(); i++) {
2326         if (indexes[i] < 0 || indexes[i] >= static_cast<int32_t>(symbolArray_.size())) {
2327             continue;
2328         }
2329         auto columnNode = DynamicCast<FrameNode>(tabBarNode->GetChildAtIndex(indexes[i]));
2330         CHECK_NULL_VOID(columnNode && !columnNode->GetChildren().empty());
2331         auto symbolNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
2332         CHECK_NULL_VOID(symbolNode);
2333         if (symbolNode->GetTag() != V2::SYMBOL_ETS_TAG) {
2334             continue;
2335         }
2336         auto symbolLayoutProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
2337         CHECK_NULL_VOID(symbolLayoutProperty);
2338         TabContentModelNG::UpdateDefaultSymbol(tabTheme, symbolLayoutProperty);
2339         if (i == 0) {
2340             symbolLayoutProperty->UpdateSymbolColorList({tabTheme->GetBottomTabSymbolOn()});
2341             auto modifierOnApply = symbolArray_[indexes[i]].onApply;
2342             UpdateSymbolApply(symbolNode, symbolLayoutProperty, indexes[i], "selected");
2343             if (preIndex != -1) {
2344                 TabContentModelNG::UpdateSymbolEffect(symbolLayoutProperty, true);
2345             }
2346         } else {
2347             symbolLayoutProperty->UpdateSymbolColorList({tabTheme->GetBottomTabSymbolOff()});
2348             UpdateSymbolApply(symbolNode, symbolLayoutProperty, indexes[i], "normal");
2349         }
2350         symbolNode->MarkModifyDone();
2351         symbolNode->MarkDirtyNode();
2352     }
2353 }
2354 
AdjustSymbolStats(int32_t index)2355 void TabBarPattern::AdjustSymbolStats(int32_t index)
2356 {
2357     auto tabBarNode = GetHost();
2358     CHECK_NULL_VOID(tabBarNode);
2359 
2360     for (int32_t i = 0; i < static_cast<int32_t>(tabBarNode->GetChildren().size()); i++) {
2361         if (i == index) {
2362             UpdateSymbolStats(index, -1);
2363             continue;
2364         }
2365 
2366         UpdateSymbolStats(-1, i);
2367     }
2368 }
2369 
UpdateSymbolApply(const RefPtr<NG::FrameNode> & symbolNode,RefPtr<TextLayoutProperty> & symbolProperty,int32_t index,std::string type)2370 void TabBarPattern::UpdateSymbolApply(const RefPtr<NG::FrameNode>& symbolNode,
2371     RefPtr<TextLayoutProperty>& symbolProperty, int32_t index, std::string type)
2372 {
2373     if (index < 0 || index >= static_cast<int32_t>(symbolArray_.size())) {
2374         return;
2375     }
2376     auto modifierOnApply = symbolArray_[index].onApply;
2377     if (type == "selected" && !symbolArray_[index].selectedFlag) {
2378         return;
2379     }
2380     if (modifierOnApply != nullptr) {
2381         modifierOnApply(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(symbolNode)), type);
2382         TabContentModelNG::UpdateSymbolEffect(symbolProperty, false);
2383     }
2384 }
2385 
UpdateSymbolEffect(int32_t index)2386 void TabBarPattern::UpdateSymbolEffect(int32_t index)
2387 {
2388     if (index != GetImageColorOnIndex().value_or(indicator_)) {
2389         return;
2390     }
2391     auto tabBarNode = GetHost();
2392     CHECK_NULL_VOID(tabBarNode);
2393     auto columnNode = DynamicCast<FrameNode>(tabBarNode->GetChildAtIndex(index));
2394     CHECK_NULL_VOID(columnNode && !columnNode->GetChildren().empty());
2395     auto symbolNode = AceType::DynamicCast<FrameNode>(columnNode->GetChildren().front());
2396     CHECK_NULL_VOID(symbolNode);
2397     if (symbolNode->GetTag() == V2::SYMBOL_ETS_TAG) {
2398         auto symbolLayoutProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
2399         CHECK_NULL_VOID(symbolLayoutProperty);
2400         auto symbolEffectOptions = symbolLayoutProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
2401         symbolEffectOptions.SetIsTxtActive(false);
2402         symbolLayoutProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
2403     }
2404 }
2405 
UpdateSubTabBoard(int32_t index)2406 void TabBarPattern::UpdateSubTabBoard(int32_t index)
2407 {
2408     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
2409     CHECK_NULL_VOID(layoutProperty);
2410     auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
2411 
2412     if (index < 0 || index >= static_cast<int32_t>(indicatorStyles_.size()) ||
2413         index >= static_cast<int32_t>(selectedModes_.size())) {
2414         return;
2415     }
2416     auto tabBarNode = GetHost();
2417     CHECK_NULL_VOID(tabBarNode);
2418     int32_t selectedColumnId = 0;
2419     int32_t focusedColumnId = 0;
2420     GetColumnId(selectedColumnId, focusedColumnId, index);
2421     auto pipelineContext = tabBarNode->GetContext();
2422     CHECK_NULL_VOID(pipelineContext);
2423     for (auto& iter : visibleItemPosition_) {
2424         if (iter.first < 0 || iter.first >= static_cast<int32_t>(tabBarStyles_.size())) {
2425             break;
2426         }
2427         auto columnFrameNode = AceType::DynamicCast<FrameNode>(tabBarNode->GetChildAtIndex(iter.first));
2428         CHECK_NULL_VOID(columnFrameNode);
2429         auto renderContext = columnFrameNode->GetRenderContext();
2430         CHECK_NULL_VOID(renderContext);
2431         if (tabBarStyles_[iter.first] == TabBarStyle::SUBTABBATSTYLE) {
2432             UpdateSubTabBarItemStyles(columnFrameNode, focusedColumnId, selectedColumnId, axis, index);
2433             columnFrameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2434         }
2435     }
2436 }
2437 
GetSelectedMode() const2438 SelectedMode TabBarPattern::GetSelectedMode() const
2439 {
2440     if (indicator_ >= static_cast<int32_t>(selectedModes_.size())) {
2441         return SelectedMode::INDICATOR;
2442     } else {
2443         return selectedModes_[indicator_];
2444     }
2445 }
2446 
IsContainsBuilder()2447 bool TabBarPattern::IsContainsBuilder()
2448 {
2449     return std::any_of(tabBarType_.begin(), tabBarType_.end(), [](const auto& isBuilder) {
2450         return isBuilder.second == TabBarParamType::CUSTOM_BUILDER ||
2451                isBuilder.second == TabBarParamType::COMPONENT_CONTENT;
2452     });
2453 }
2454 
PlayTabBarTranslateAnimation(AnimationOption option,float targetCurrentOffset)2455 void TabBarPattern::PlayTabBarTranslateAnimation(AnimationOption option, float targetCurrentOffset)
2456 {
2457     auto weak = AceType::WeakClaim(this);
2458     auto host = GetHost();
2459 
2460     currentOffset_ = 0.0f;
2461     host->CreateAnimatablePropertyFloat(TAB_BAR_PROPERTY_NAME, 0, [weak](float value) {
2462         auto tabBarPattern = weak.Upgrade();
2463         CHECK_NULL_VOID(tabBarPattern);
2464         tabBarPattern->currentDelta_ = value - tabBarPattern->currentOffset_;
2465         tabBarPattern->currentOffset_ = value;
2466         auto host = tabBarPattern->GetHost();
2467         host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2468     });
2469     host->UpdateAnimatablePropertyFloat(TAB_BAR_PROPERTY_NAME, currentOffset_);
2470     translateAnimationIsRunning_ = true;
2471     translateAnimation_ = AnimationUtils::StartAnimation(option,
2472         [weakHost = WeakClaim(RawPtr(host)), targetCurrentOffset]() {
2473             auto host = weakHost.Upgrade();
2474             CHECK_NULL_VOID(host);
2475             host->UpdateAnimatablePropertyFloat(TAB_BAR_PROPERTY_NAME, targetCurrentOffset);
2476         },
2477         [weak]() {
2478             auto tabBarPattern = weak.Upgrade();
2479             CHECK_NULL_VOID(tabBarPattern);
2480             tabBarPattern->translateAnimationIsRunning_ = false;
2481         });
2482 }
2483 
PlayIndicatorTranslateAnimation(AnimationOption option,RectF originalPaintRect,RectF targetPaintRect,float targetOffset)2484 void TabBarPattern::PlayIndicatorTranslateAnimation(AnimationOption option, RectF originalPaintRect,
2485     RectF targetPaintRect, float targetOffset)
2486 {
2487     auto host = GetHost();
2488     CHECK_NULL_VOID(host);
2489 
2490     isAnimating_ = true;
2491     turnPageRate_ = 0.0f;
2492     indicatorStartPos_ = originalPaintRect.GetX() + originalPaintRect.Width() / HALF_OF_WIDTH;
2493     indicatorEndPos_ = targetPaintRect.GetX() + targetPaintRect.Width() / HALF_OF_WIDTH + targetOffset;
2494     auto propertyName = INDICATOR_OFFSET_PROPERTY_NAME;
2495     if (NearZero(indicatorEndPos_ - indicatorStartPos_)) {
2496         indicatorStartPos_ = originalPaintRect.Width();
2497         indicatorEndPos_ = targetPaintRect.Width();
2498         propertyName = INDICATOR_WIDTH_PROPERTY_NAME;
2499     }
2500     CreateIndicatorTranslateProperty(host, propertyName);
2501 
2502     host->UpdateAnimatablePropertyFloat(propertyName, indicatorStartPos_);
2503     indicatorAnimationIsRunning_ = true;
2504     tabbarIndicatorAnimation_ = AnimationUtils::StartAnimation(option,
2505         [weakHost = WeakClaim(RawPtr(host)), propertyName, endPos = indicatorEndPos_]() {
2506             auto host = weakHost.Upgrade();
2507             CHECK_NULL_VOID(host);
2508             host->UpdateAnimatablePropertyFloat(propertyName, endPos);
2509         },
2510         [weak = AceType::WeakClaim(this)]() {
2511             auto tabBarPattern = weak.Upgrade();
2512             CHECK_NULL_VOID(tabBarPattern);
2513             tabBarPattern->indicatorAnimationIsRunning_ = false;
2514         });
2515 }
2516 
CreateIndicatorTranslateProperty(const RefPtr<FrameNode> & host,const std::string & propertyName)2517 void TabBarPattern::CreateIndicatorTranslateProperty(const RefPtr<FrameNode>& host, const std::string& propertyName)
2518 {
2519     if (propertyName == INDICATOR_WIDTH_PROPERTY_NAME) {
2520         host->CreateAnimatablePropertyFloat(propertyName, 0, [weak = AceType::WeakClaim(this)](float value) {
2521             auto tabBarPattern = weak.Upgrade();
2522             CHECK_NULL_VOID(tabBarPattern);
2523             if (!tabBarPattern->isAnimating_ ||
2524                 NearZero(tabBarPattern->indicatorEndPos_ - tabBarPattern->indicatorStartPos_)) {
2525                 return;
2526             }
2527             tabBarPattern->turnPageRate_ = (value - tabBarPattern->indicatorStartPos_) /
2528                 (tabBarPattern->indicatorEndPos_ - tabBarPattern->indicatorStartPos_);
2529             tabBarPattern->UpdateIndicatorCurrentOffset(0.0f);
2530         });
2531     } else if (propertyName == INDICATOR_OFFSET_PROPERTY_NAME) {
2532         host->CreateAnimatablePropertyFloat(propertyName, 0, [weak = AceType::WeakClaim(this)](float value) {
2533             auto tabBarPattern = weak.Upgrade();
2534             CHECK_NULL_VOID(tabBarPattern);
2535             if (!tabBarPattern->isAnimating_ ||
2536                 NearZero(tabBarPattern->indicatorEndPos_ - tabBarPattern->indicatorStartPos_)) {
2537                 return;
2538             }
2539             tabBarPattern->turnPageRate_ = (value - tabBarPattern->indicatorStartPos_) /
2540                 (tabBarPattern->indicatorEndPos_ - tabBarPattern->indicatorStartPos_);
2541             tabBarPattern->UpdateIndicatorCurrentOffset(
2542                 static_cast<float>(value - tabBarPattern->currentIndicatorOffset_));
2543         });
2544     }
2545 }
2546 
StopTranslateAnimation(bool isImmediately)2547 void TabBarPattern::StopTranslateAnimation(bool isImmediately)
2548 {
2549     if (isImmediately) {
2550         AnimationOption option;
2551         option.SetDuration(0);
2552         option.SetCurve(Curves::LINEAR);
2553         AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
2554             auto pattern = weak.Upgrade();
2555             CHECK_NULL_VOID(pattern);
2556             auto host = pattern->GetHost();
2557             CHECK_NULL_VOID(host);
2558             host->UpdateAnimatablePropertyFloat(TAB_BAR_PROPERTY_NAME, pattern->currentOffset_);
2559         });
2560     } else {
2561         if (translateAnimation_) {
2562             AnimationUtils::StopAnimation(translateAnimation_);
2563         }
2564     }
2565 
2566     if (tabbarIndicatorAnimation_) {
2567         AnimationUtils::StopAnimation(tabbarIndicatorAnimation_);
2568     }
2569 
2570     indicatorAnimationIsRunning_ = false;
2571     translateAnimationIsRunning_ = false;
2572     isAnimating_ = false;
2573 }
2574 
TriggerTranslateAnimation(int32_t currentIndex,int32_t targetIndex)2575 void TabBarPattern::TriggerTranslateAnimation(int32_t currentIndex, int32_t targetIndex)
2576 {
2577     auto curve = DurationCubicCurve;
2578     StopTranslateAnimation();
2579     SetSwiperCurve(curve);
2580     auto pipelineContext = GetContext();
2581     CHECK_NULL_VOID(pipelineContext);
2582     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
2583     CHECK_NULL_VOID(tabTheme);
2584     UpdateAnimationDuration();
2585     AnimationOption option = AnimationOption();
2586     option.SetDuration(static_cast<int32_t>(GetAnimationDuration().value_or(
2587         tabTheme->GetTabContentAnimationDuration())));
2588     option.SetCurve(curve);
2589     option.SetFillMode(FillMode::FORWARDS);
2590 
2591     auto targetOffset = 0.0f;
2592     if (CanScroll()) {
2593         targetOffset = CalculateTargetOffset(targetIndex);
2594         PlayTabBarTranslateAnimation(option, targetOffset);
2595     }
2596 
2597     auto host = GetHost();
2598     CHECK_NULL_VOID(host);
2599     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
2600     CHECK_NULL_VOID(layoutProperty);
2601     if (std::count(tabBarStyles_.begin(), tabBarStyles_.end(), TabBarStyle::SUBTABBATSTYLE) !=
2602             static_cast<int32_t>(tabBarStyles_.size()) ||
2603         layoutProperty->GetAxisValue(Axis::HORIZONTAL) != Axis::HORIZONTAL) {
2604         return;
2605     }
2606     auto paintProperty = host->GetPaintProperty<TabBarPaintProperty>();
2607     CHECK_NULL_VOID(paintProperty);
2608     paintProperty->UpdateIndicator(targetIndex);
2609     if (!changeByClick_) {
2610         return;
2611     }
2612     auto originalPaintRect = GetOriginalPaintRect(currentIndex);
2613     auto targetPaintRect = layoutProperty->GetIndicatorRect(targetIndex);
2614     PlayIndicatorTranslateAnimation(option, originalPaintRect, targetPaintRect, targetOffset);
2615 }
2616 
GetOriginalPaintRect(int32_t currentIndex)2617 RectF TabBarPattern::GetOriginalPaintRect(int32_t currentIndex)
2618 {
2619     auto host = GetHost();
2620     CHECK_NULL_RETURN(host, RectF());
2621     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
2622     CHECK_NULL_RETURN(layoutProperty, RectF());
2623     auto originalPaintRect = layoutProperty->GetIndicatorRect(currentIndex);
2624     if (!visibleItemPosition_.empty()) {
2625         auto mainSize = GetContentSize().MainSize(axis_);
2626         if (currentIndex >= 0 && currentIndex < visibleItemPosition_.begin()->first) {
2627             if (isRTL_) {
2628                 originalPaintRect.SetLeft(mainSize - visibleItemPosition_.begin()->second.startPos);
2629             } else {
2630                 originalPaintRect.SetLeft(visibleItemPosition_.begin()->second.startPos - originalPaintRect.Width());
2631             }
2632             currentIndicatorOffset_ = originalPaintRect.GetX() + originalPaintRect.Width() / HALF_OF_WIDTH;
2633         } else if (currentIndex < host->TotalChildCount() - MASK_COUNT &&
2634             currentIndex > visibleItemPosition_.rbegin()->first) {
2635             if (isRTL_) {
2636                 originalPaintRect.SetLeft(
2637                     mainSize - visibleItemPosition_.rbegin()->second.endPos - originalPaintRect.Width());
2638             } else {
2639                 originalPaintRect.SetLeft(visibleItemPosition_.rbegin()->second.endPos);
2640             }
2641             currentIndicatorOffset_ = originalPaintRect.GetX() + originalPaintRect.Width() / HALF_OF_WIDTH;
2642         }
2643     }
2644     return originalPaintRect;
2645 }
2646 
CalculateTargetOffset(int32_t targetIndex)2647 float TabBarPattern::CalculateTargetOffset(int32_t targetIndex)
2648 {
2649     auto targetOffset = 0.0f;
2650     auto space = GetSpace(targetIndex);
2651     auto startPos = 0.0f;
2652     auto endPos = 0.0f;
2653     auto iter = visibleItemPosition_.find(targetIndex);
2654     if (iter != visibleItemPosition_.end()) {
2655         startPos = iter->second.startPos;
2656         endPos = iter->second.endPos;
2657     }
2658     auto frontChildrenMainSize = CalculateFrontChildrenMainSize(targetIndex);
2659     auto backChildrenMainSize = CalculateBackChildrenMainSize(targetIndex);
2660     if (Negative(space)) {
2661         targetOffset = isRTL_ && axis_ == Axis::HORIZONTAL ? (startPos - scrollMargin_)
2662                                                             : (scrollMargin_ - startPos);
2663     } else if (LessOrEqual(frontChildrenMainSize, space)) {
2664         targetOffset = isRTL_ && axis_ == Axis::HORIZONTAL ? (startPos - frontChildrenMainSize)
2665                                                             : (frontChildrenMainSize - startPos);
2666     } else if (LessOrEqual(backChildrenMainSize, space)) {
2667         auto mainSize = GetContentSize().MainSize(axis_);
2668         targetOffset = isRTL_ && axis_ == Axis::HORIZONTAL ? (backChildrenMainSize - (mainSize - endPos))
2669                                                             : (mainSize - backChildrenMainSize - endPos);
2670     } else {
2671         targetOffset = isRTL_ && axis_ == Axis::HORIZONTAL ? (startPos - space) : (space - startPos);
2672     }
2673     return targetOffset;
2674 }
2675 
UpdateIndicatorCurrentOffset(float offset)2676 void TabBarPattern::UpdateIndicatorCurrentOffset(float offset)
2677 {
2678     currentIndicatorOffset_ = currentIndicatorOffset_ + offset;
2679     auto host = GetHost();
2680     CHECK_NULL_VOID(host);
2681     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2682 }
2683 
CreateNodePaintMethod()2684 RefPtr<NodePaintMethod> TabBarPattern::CreateNodePaintMethod()
2685 {
2686     if (!tabBarModifier_) {
2687         tabBarModifier_ = AceType::MakeRefPtr<TabBarModifier>();
2688     }
2689     auto host = GetHost();
2690     CHECK_NULL_RETURN(host, nullptr);
2691     auto geometryNode = host->GetGeometryNode();
2692     CHECK_NULL_RETURN(geometryNode, nullptr);
2693     auto tabBarRect = geometryNode->GetFrameRect(true);
2694     Color bgColor = GetTabBarBackgroundColor();
2695     RectF tabBarItemRect;
2696     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
2697     auto paintProperty = GetPaintProperty<TabBarPaintProperty>();
2698     if (layoutProperty && paintProperty && paintProperty->GetIndicator().has_value()) {
2699         tabBarItemRect = layoutProperty->GetIndicatorRect(paintProperty->GetIndicator().value());
2700     }
2701     IndicatorStyle indicatorStyle;
2702     OffsetF indicatorOffset = { currentIndicatorOffset_, tabBarItemRect.GetY() };
2703     GetIndicatorStyle(indicatorStyle, indicatorOffset, tabBarItemRect);
2704     indicatorOffset.AddX(-indicatorStyle.width.ConvertToPx() / HALF_OF_WIDTH);
2705     auto hasIndicator = indicator_ < static_cast<int32_t>(selectedModes_.size()) ?
2706         std::count(selectedModes_.begin(), selectedModes_.end(), SelectedMode::INDICATOR) ==
2707         static_cast<int32_t>(selectedModes_.size()) && !NearZero(tabBarItemRect.Height()) : 0;
2708     return MakeRefPtr<TabBarPaintMethod>(tabBarModifier_, tabBarRect, gradientRegions_, bgColor, indicatorStyle,
2709         indicatorOffset, hasIndicator);
2710 }
2711 
GetTabBarBackgroundColor() const2712 Color TabBarPattern::GetTabBarBackgroundColor() const
2713 {
2714     Color bgColor = Color::WHITE;
2715     auto tabBarNode = GetHost();
2716     CHECK_NULL_RETURN(tabBarNode, bgColor);
2717     auto tabBarCtx = tabBarNode->GetRenderContext();
2718     CHECK_NULL_RETURN(tabBarCtx, bgColor);
2719     if (tabBarCtx->GetBackgroundColor()) {
2720         bgColor = *tabBarCtx->GetBackgroundColor();
2721     } else {
2722         auto tabsNode = AceType::DynamicCast<FrameNode>(tabBarNode->GetParent());
2723         CHECK_NULL_RETURN(tabsNode, bgColor);
2724         auto tabsCtx = tabsNode->GetRenderContext();
2725         CHECK_NULL_RETURN(tabsCtx, bgColor);
2726         if (tabsCtx->GetBackgroundColor()) {
2727             bgColor = *tabsCtx->GetBackgroundColor();
2728         } else {
2729             auto pipeline = tabBarNode->GetContext();
2730             CHECK_NULL_RETURN(pipeline, bgColor);
2731             auto tabTheme = pipeline->GetTheme<TabTheme>();
2732             CHECK_NULL_RETURN(tabTheme, bgColor);
2733             bgColor = tabTheme->GetBackgroundColor().ChangeAlpha(0xff);
2734         }
2735     }
2736     return bgColor;
2737 }
2738 
GetIndicatorStyle(IndicatorStyle & indicatorStyle,OffsetF & indicatorOffset,RectF & tabBarItemRect)2739 void TabBarPattern::GetIndicatorStyle(IndicatorStyle& indicatorStyle, OffsetF& indicatorOffset, RectF& tabBarItemRect)
2740 {
2741     if (indicator_ < 0 || indicator_ >= static_cast<int32_t>(indicatorStyles_.size())) {
2742         return;
2743     }
2744     indicatorStyle = indicatorStyles_[indicator_];
2745     if (NonPositive(indicatorStyle.width.Value())) {
2746         indicatorStyle.width = Dimension(tabBarItemRect.Width());
2747     }
2748     if ((!isTouchingSwiper_ && !isAnimating_) || axis_ != Axis::HORIZONTAL) {
2749         return;
2750     }
2751     if (LessOrEqual(turnPageRate_, 0.0f)) {
2752         turnPageRate_ = 0.0f;
2753     }
2754     if (GreatOrEqual(turnPageRate_, 1.0f)) {
2755         turnPageRate_ = 1.0f;
2756     }
2757 
2758     auto host = GetHost();
2759     CHECK_NULL_VOID(host);
2760     auto totalCount = host->TotalChildCount() - MASK_COUNT;
2761     if (!IsValidIndex(swiperStartIndex_) || swiperStartIndex_ >= totalCount ||
2762         swiperStartIndex_ >= static_cast<int32_t>(indicatorStyles_.size())) {
2763         return;
2764     }
2765 
2766     auto nextIndex = isTouchingSwiper_ ? swiperStartIndex_ + 1 : animationTargetIndex_.value_or(-1);
2767     if (!IsValidIndex(nextIndex) || nextIndex >= totalCount ||
2768         nextIndex >= static_cast<int32_t>(indicatorStyles_.size())) {
2769         return;
2770     }
2771     CalculateIndicatorStyle(swiperStartIndex_, nextIndex, indicatorStyle, indicatorOffset);
2772 }
2773 
CalculateIndicatorStyle(int32_t startIndex,int32_t nextIndex,IndicatorStyle & indicatorStyle,OffsetF & indicatorOffset)2774 void TabBarPattern::CalculateIndicatorStyle(
2775     int32_t startIndex, int32_t nextIndex, IndicatorStyle& indicatorStyle, OffsetF& indicatorOffset)
2776 {
2777     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
2778     CHECK_NULL_VOID(layoutProperty);
2779 
2780     indicatorStyle = indicatorStyles_[startIndex];
2781     auto startItemRect = layoutProperty->GetIndicatorRect(startIndex);
2782     if (NonPositive(indicatorStyle.width.Value())) {
2783         indicatorStyle.width = Dimension(startItemRect.Width());
2784     }
2785     IndicatorStyle nextIndicatorStyle = indicatorStyles_[nextIndex];
2786     auto nextItemRect = layoutProperty->GetIndicatorRect(nextIndex);
2787     if (NonPositive(nextIndicatorStyle.width.Value())) {
2788         nextIndicatorStyle.width = Dimension(nextItemRect.Width());
2789     }
2790 
2791     indicatorStyle.width = Dimension(indicatorStyle.width.ConvertToPx() +
2792         (nextIndicatorStyle.width.ConvertToPx() - indicatorStyle.width.ConvertToPx()) * turnPageRate_);
2793     indicatorStyle.marginTop = Dimension(indicatorStyle.marginTop.ConvertToPx() +
2794         (nextIndicatorStyle.marginTop.ConvertToPx() - indicatorStyle.marginTop.ConvertToPx()) * turnPageRate_);
2795     indicatorStyle.height = Dimension(indicatorStyle.height.ConvertToPx() +
2796         (nextIndicatorStyle.height.ConvertToPx() - indicatorStyle.height.ConvertToPx()) * turnPageRate_);
2797     LinearColor color = LinearColor(indicatorStyle.color) +
2798         (LinearColor(nextIndicatorStyle.color) - LinearColor(indicatorStyle.color)) * turnPageRate_;
2799     indicatorStyle.color = color.ToColor();
2800     indicatorOffset.SetY(startItemRect.GetY() + (nextItemRect.GetY() - startItemRect.GetY()) * turnPageRate_);
2801 }
2802 
GetSpace(int32_t indicator)2803 float TabBarPattern::GetSpace(int32_t indicator)
2804 {
2805     auto host = GetHost();
2806     CHECK_NULL_RETURN(host, 0.0f);
2807     auto childFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(indicator));
2808     CHECK_NULL_RETURN(childFrameNode, 0.0f);
2809     auto childGeometryNode = childFrameNode->GetGeometryNode();
2810 
2811     return (GetContentSize().MainSize(axis_) - childGeometryNode->GetMarginFrameSize().MainSize(axis_)) / 2;
2812 }
2813 
CalculateFrontChildrenMainSize(int32_t indicator)2814 float TabBarPattern::CalculateFrontChildrenMainSize(int32_t indicator)
2815 {
2816     float frontChildrenMainSize = scrollMargin_;
2817     if (visibleItemPosition_.empty()) {
2818         return frontChildrenMainSize;
2819     }
2820     for (auto& iter : visibleItemPosition_) {
2821         if (iter.first < indicator) {
2822             frontChildrenMainSize += iter.second.endPos - iter.second.startPos;
2823         }
2824     }
2825     return frontChildrenMainSize;
2826 }
2827 
CalculateBackChildrenMainSize(int32_t indicator)2828 float TabBarPattern::CalculateBackChildrenMainSize(int32_t indicator)
2829 {
2830     float backChildrenMainSize = scrollMargin_;
2831     if (visibleItemPosition_.empty()) {
2832         return backChildrenMainSize;
2833     }
2834     for (auto& iter : visibleItemPosition_) {
2835         if (iter.first > indicator) {
2836             backChildrenMainSize += iter.second.endPos - iter.second.startPos;
2837         }
2838     }
2839     return backChildrenMainSize;
2840 }
2841 
SetEdgeEffect(const RefPtr<GestureEventHub> & gestureHub)2842 void TabBarPattern::SetEdgeEffect(const RefPtr<GestureEventHub>& gestureHub)
2843 {
2844     CHECK_NULL_VOID(gestureHub);
2845     if (scrollEffect_) {
2846         gestureHub->RemoveScrollEdgeEffect(scrollEffect_);
2847         scrollEffect_.Reset();
2848     }
2849     if (!scrollEffect_) {
2850         auto springEffect = AceType::MakeRefPtr<ScrollSpringEffect>();
2851         CHECK_NULL_VOID(springEffect);
2852         springEffect->SetOutBoundaryCallback([weak = AceType::WeakClaim(this)]() {
2853             auto pattern = weak.Upgrade();
2854             CHECK_NULL_RETURN(pattern, false);
2855             return pattern->IsAtTop() || pattern->IsAtBottom();
2856         });
2857         // add callback to springEdgeEffect
2858         SetEdgeEffectCallback(springEffect);
2859         scrollEffect_ = springEffect;
2860         gestureHub->AddScrollEdgeEffect(axis_, scrollEffect_);
2861     }
2862 }
2863 
SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect> & scrollEffect)2864 void TabBarPattern::SetEdgeEffectCallback(const RefPtr<ScrollEdgeEffect>& scrollEffect)
2865 {
2866     scrollEffect->SetCurrentPositionCallback([weak = AceType::WeakClaim(this)]() -> double {
2867         auto tabBar = weak.Upgrade();
2868         CHECK_NULL_RETURN(tabBar, 0.0);
2869         if (tabBar->visibleItemPosition_.empty()) {
2870             return tabBar->scrollMargin_ + tabBar->currentDelta_;
2871         }
2872         if (tabBar->isRTL_ && tabBar->axis_ == Axis::HORIZONTAL) {
2873             return tabBar->GetContentSize().Width() - tabBar->visibleItemPosition_.rbegin()->second.endPos +
2874                 tabBar->currentDelta_;
2875         } else {
2876             return tabBar->visibleItemPosition_.begin()->second.startPos + tabBar->currentDelta_;
2877         }
2878     });
2879     auto leadingCallback = [weak = AceType::WeakClaim(this)]() -> double {
2880         auto tabBar = weak.Upgrade();
2881         CHECK_NULL_RETURN(tabBar, 0.0);
2882         if (tabBar->visibleItemPosition_.empty()) {
2883             return tabBar->GetContentSize().MainSize(tabBar->axis_) - tabBar->scrollMargin_;
2884         }
2885         auto visibleChildrenMainSize = tabBar->visibleItemPosition_.rbegin()->second.endPos -
2886             tabBar->visibleItemPosition_.begin()->second.startPos;
2887         return tabBar->GetContentSize().MainSize(tabBar->axis_) - visibleChildrenMainSize - tabBar->scrollMargin_;
2888     };
2889     auto trailingCallback = [weak = AceType::WeakClaim(this)]() -> double {
2890         auto tabBar = weak.Upgrade();
2891         CHECK_NULL_RETURN(tabBar, 0.0);
2892         return tabBar->scrollMargin_;
2893     };
2894     scrollEffect->SetLeadingCallback(leadingCallback);
2895     scrollEffect->SetTrailingCallback(trailingCallback);
2896     scrollEffect->SetInitLeadingCallback(leadingCallback);
2897     scrollEffect->SetInitTrailingCallback(trailingCallback);
2898 }
2899 
IsAtTop() const2900 bool TabBarPattern::IsAtTop() const
2901 {
2902     if (visibleItemPosition_.empty()) {
2903         return false;
2904     }
2905 
2906     auto visibleItemStartIndex = visibleItemPosition_.begin()->first;
2907     auto visibleItemStartPos = visibleItemPosition_.begin()->second.startPos;
2908     return visibleItemStartIndex == 0 && GreatOrEqual(visibleItemStartPos, scrollMargin_);
2909 }
2910 
IsAtBottom() const2911 bool TabBarPattern::IsAtBottom() const
2912 {
2913     if (visibleItemPosition_.empty()) {
2914         return false;
2915     }
2916     auto host = GetHost();
2917     CHECK_NULL_RETURN(host, false);
2918 
2919     auto visibleItemEndIndex = visibleItemPosition_.rbegin()->first;
2920     auto visibleItemEndPos = visibleItemPosition_.rbegin()->second.endPos;
2921     auto childCount = host->TotalChildCount() - MASK_COUNT;
2922     auto mainSize = GetContentSize().MainSize(axis_);
2923     return visibleItemEndIndex == (childCount - 1) && LessOrEqual(visibleItemEndPos, mainSize - scrollMargin_);
2924 }
2925 
IsOutOfBoundary()2926 bool TabBarPattern::IsOutOfBoundary()
2927 {
2928     if (visibleItemPosition_.empty()) {
2929         return false;
2930     }
2931 
2932     auto visibleItemStartPos = visibleItemPosition_.begin()->second.startPos;
2933     auto visibleItemEndPos = visibleItemPosition_.rbegin()->second.endPos;
2934     auto mainSize = GetContentSize().MainSize(axis_);
2935     bool outOfStart = Positive(visibleItemStartPos - scrollMargin_) &&
2936         GreatNotEqual(visibleItemEndPos + scrollMargin_, mainSize);
2937     bool outOfEnd = LessNotEqual(visibleItemEndPos + scrollMargin_, mainSize) &&
2938         Negative(visibleItemStartPos - scrollMargin_);
2939     return outOfStart || outOfEnd;
2940 }
2941 
SetAccessibilityAction()2942 void TabBarPattern::SetAccessibilityAction()
2943 {
2944     auto host = GetHost();
2945     CHECK_NULL_VOID(host);
2946     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
2947     CHECK_NULL_VOID(accessibilityProperty);
2948     accessibilityProperty->SetActionScrollForward([weakPtr = WeakClaim(this)]() {
2949         const auto& pattern = weakPtr.Upgrade();
2950         CHECK_NULL_VOID(pattern);
2951         auto tabBarLayoutProperty = pattern->GetLayoutProperty<TabBarLayoutProperty>();
2952         CHECK_NULL_VOID(tabBarLayoutProperty);
2953         auto frameNode = pattern->GetHost();
2954         CHECK_NULL_VOID(frameNode);
2955         if (tabBarLayoutProperty->GetTabBarMode().value_or(TabBarMode::FIXED) == TabBarMode::SCROLLABLE &&
2956             frameNode->TotalChildCount() - MASK_COUNT > 1) {
2957             auto index =
2958                 std::clamp(pattern->accessibilityFocusIndicator_ + 1, 0, frameNode->TotalChildCount() - MASK_COUNT - 1);
2959             pattern->FocusCurrentOffset(index);
2960             // AccessibilityEventType::SCROLL_END
2961         }
2962     });
2963 
2964     accessibilityProperty->SetActionScrollBackward([weakPtr = WeakClaim(this)]() {
2965         const auto& pattern = weakPtr.Upgrade();
2966         CHECK_NULL_VOID(pattern);
2967         auto tabBarLayoutProperty = pattern->GetLayoutProperty<TabBarLayoutProperty>();
2968         CHECK_NULL_VOID(tabBarLayoutProperty);
2969         auto frameNode = pattern->GetHost();
2970         CHECK_NULL_VOID(frameNode);
2971         if (tabBarLayoutProperty->GetTabBarMode().value_or(TabBarMode::FIXED) == TabBarMode::SCROLLABLE &&
2972            frameNode->TotalChildCount() - MASK_COUNT > 1) {
2973             auto index =
2974                 std::clamp(pattern->accessibilityFocusIndicator_ - 1, 0, frameNode->TotalChildCount() - MASK_COUNT - 1);
2975             pattern->FocusCurrentOffset(index);
2976             // AccessibilityEventType::SCROLL_END
2977         }
2978     });
2979 }
2980 
ProvideRestoreInfo()2981 std::string TabBarPattern::ProvideRestoreInfo()
2982 {
2983     auto jsonObj = JsonUtil::Create(true);
2984     auto tabBarLayoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
2985     CHECK_NULL_RETURN(tabBarLayoutProperty, "");
2986     jsonObj->Put("Index", tabBarLayoutProperty->GetIndicator().value_or(0));
2987     return jsonObj->ToString();
2988 }
2989 
OnRestoreInfo(const std::string & restoreInfo)2990 void TabBarPattern::OnRestoreInfo(const std::string& restoreInfo)
2991 {
2992     auto host = GetHost();
2993     CHECK_NULL_VOID(host);
2994     auto info = JsonUtil::ParseJsonString(restoreInfo);
2995     if (!info->IsValid() || !info->IsObject()) {
2996         return;
2997     }
2998     auto jsonIsOn = info->GetValue("Index");
2999     auto index = jsonIsOn->GetInt();
3000     auto totalCount = host->TotalChildCount();
3001     if (index < 0 || index >= totalCount || !swiperController_ ||
3002         indicator_ >= static_cast<int32_t>(tabBarStyles_.size())) {
3003         return;
3004     }
3005     auto tabsFrameNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3006     CHECK_NULL_VOID(tabsFrameNode);
3007     auto tabsPattern = tabsFrameNode->GetPattern<TabsPattern>();
3008     UpdateIndicator(index);
3009     UpdateAnimationDuration();
3010     if (GetAnimationDuration().has_value()
3011         && (!tabsPattern || tabsPattern->GetAnimateMode() != TabAnimateMode::NO_ANIMATION)) {
3012         swiperController_->SwipeTo(index);
3013     } else {
3014         swiperController_->SwipeToWithoutAnimation(index);
3015     }
3016 }
3017 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const3018 void TabBarPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
3019 {
3020     Pattern::ToJsonValue(json, filter);
3021     /* no fixed attr below, just return */
3022     if (filter.IsFastFilter()) {
3023         return;
3024     }
3025     auto selectedModes = JsonUtil::CreateArray(true);
3026     for (const auto& selectedMode : selectedModes_) {
3027         auto mode = JsonUtil::Create(true);
3028         mode->Put("mode", selectedMode == SelectedMode::INDICATOR ? "INDICATOR" : "BOARD");
3029         selectedModes->Put(mode);
3030     }
3031     json->PutExtAttr("selectedModes", selectedModes->ToString().c_str(), filter);
3032 
3033     auto indicatorStyles = JsonUtil::CreateArray(true);
3034     for (const auto& indicatorStyle : indicatorStyles_) {
3035         auto indicator = JsonUtil::Create(true);
3036         indicator->Put("color", indicatorStyle.color.ColorToString().c_str());
3037         indicator->Put("height", indicatorStyle.height.ToString().c_str());
3038         indicator->Put("width", indicatorStyle.width.ToString().c_str());
3039         indicator->Put("borderRadius", indicatorStyle.borderRadius.ToString().c_str());
3040         indicator->Put("marginTop", indicatorStyle.marginTop.ToString().c_str());
3041         indicatorStyles->Put(indicator);
3042     }
3043     json->PutExtAttr("indicatorStyles", indicatorStyles->ToString().c_str(), filter);
3044 
3045     auto tabBarStyles = JsonUtil::CreateArray(true);
3046     for (const auto& tabBarStyle : tabBarStyles_) {
3047         auto style = JsonUtil::Create(true);
3048         style->Put("style", tabBarStyle == TabBarStyle::NOSTYLE          ? "NOSTYLE"
3049                             : tabBarStyle == TabBarStyle::SUBTABBATSTYLE ? "SUBTABBATSTYLE"
3050                                                                          : "BOTTOMTABBATSTYLE");
3051         tabBarStyles->Put(style);
3052     }
3053     json->PutExtAttr("tabBarStyles", tabBarStyles->ToString().c_str(), filter);
3054 }
3055 
FromJson(const std::unique_ptr<JsonValue> & json)3056 void TabBarPattern::FromJson(const std::unique_ptr<JsonValue>& json)
3057 {
3058     auto selectedModes = JsonUtil::ParseJsonString(json->GetString("selectedModes"));
3059     for (int32_t i = 0; i < selectedModes->GetArraySize(); i++) {
3060         auto selectedMode = selectedModes->GetArrayItem(i);
3061         auto mode = selectedMode->GetString("mode");
3062         SetSelectedMode(mode == "INDICATOR" ? SelectedMode::INDICATOR : SelectedMode::BOARD, i);
3063     }
3064 
3065     auto indicatorStyles = JsonUtil::ParseJsonString(json->GetString("indicatorStyles"));
3066     for (int32_t i = 0; i < indicatorStyles->GetArraySize(); i++) {
3067         auto indicatorStyle = indicatorStyles->GetArrayItem(i);
3068         IndicatorStyle style;
3069         style.color = Color::ColorFromString(indicatorStyle->GetString("color"));
3070         style.height = Dimension::FromString(indicatorStyle->GetString("height"));
3071         style.width = Dimension::FromString(indicatorStyle->GetString("width"));
3072         style.borderRadius = Dimension::FromString(indicatorStyle->GetString("borderRadius"));
3073         style.marginTop = Dimension::FromString(indicatorStyle->GetString("marginTop"));
3074         SetIndicatorStyle(style, i);
3075     }
3076 
3077     auto tabBarStyles = JsonUtil::ParseJsonString(json->GetString("tabBarStyles"));
3078     for (int32_t i = 0; i < tabBarStyles->GetArraySize(); i++) {
3079         auto tabBarStyle = tabBarStyles->GetArrayItem(i);
3080         auto style = tabBarStyle->GetString("style");
3081         SetTabBarStyle(style == "NOSTYLE"          ? TabBarStyle::NOSTYLE
3082                        : style == "SUBTABBATSTYLE" ? TabBarStyle::SUBTABBATSTYLE
3083                                                    : TabBarStyle::BOTTOMTABBATSTYLE,
3084             i);
3085     }
3086 
3087     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
3088     CHECK_NULL_VOID(layoutProperty);
3089     auto indicatorValue = layoutProperty->GetIndicatorValue(0);
3090     UpdateIndicator(indicatorValue);
3091     UpdatePaintIndicator(indicatorValue, true);
3092     Pattern::FromJson(json);
3093 }
3094 
TabBarClickEvent(int32_t index) const3095 void TabBarPattern::TabBarClickEvent(int32_t index) const
3096 {
3097     auto host = GetHost();
3098     CHECK_NULL_VOID(host);
3099     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3100     CHECK_NULL_VOID(tabsNode);
3101     auto tabsPattern = tabsNode->GetPattern<TabsPattern>();
3102     CHECK_NULL_VOID(tabsPattern);
3103     auto tabBarClickEvent = tabsPattern->GetTabBarClickEvent();
3104     CHECK_NULL_VOID(tabBarClickEvent);
3105     auto event = *tabBarClickEvent;
3106     event(index);
3107 }
3108 
3109 
OnCustomContentTransition(int32_t fromIndex,int32_t toIndex)3110 void TabBarPattern::OnCustomContentTransition(int32_t fromIndex, int32_t toIndex)
3111 {
3112     auto swiperPattern = GetSwiperPattern();
3113     CHECK_NULL_VOID(swiperPattern);
3114 
3115     swiperPattern->OnCustomContentTransition(toIndex);
3116 }
3117 
GetSwiperPattern() const3118 RefPtr<SwiperPattern> TabBarPattern::GetSwiperPattern() const
3119 {
3120     auto host = GetHost();
3121     CHECK_NULL_RETURN(host, nullptr);
3122     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3123     CHECK_NULL_RETURN(tabsNode, nullptr);
3124     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
3125     CHECK_NULL_RETURN(swiperNode, nullptr);
3126     auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
3127     return swiperPattern;
3128 }
3129 
CheckSwiperDisable() const3130 bool TabBarPattern::CheckSwiperDisable() const
3131 {
3132     auto host = GetHost();
3133     CHECK_NULL_RETURN(host, true);
3134     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3135     CHECK_NULL_RETURN(tabsNode, true);
3136     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
3137     CHECK_NULL_RETURN(swiperNode, true);
3138     auto props = swiperNode->GetLayoutProperty<SwiperLayoutProperty>();
3139     CHECK_NULL_RETURN(props, true);
3140     return props->GetDisableSwipe().value_or(false);
3141 }
3142 
SetSwiperCurve(const RefPtr<Curve> & curve) const3143 void TabBarPattern::SetSwiperCurve(const RefPtr<Curve>& curve) const
3144 {
3145     auto host = GetHost();
3146     CHECK_NULL_VOID(host);
3147     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3148     CHECK_NULL_VOID(tabsNode);
3149     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
3150     CHECK_NULL_VOID(swiperNode);
3151     auto swiperPaintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
3152     CHECK_NULL_VOID(swiperPaintProperty);
3153     swiperPaintProperty->UpdateCurve(curve);
3154 }
3155 
ApplyTurnPageRateToIndicator(float turnPageRate)3156 void TabBarPattern::ApplyTurnPageRateToIndicator(float turnPageRate)
3157 {
3158     auto host = GetHost();
3159     CHECK_NULL_VOID(host);
3160     auto layoutProperty = host->GetLayoutProperty<TabBarLayoutProperty>();
3161     auto totalCount = host->TotalChildCount() - MASK_COUNT;
3162     CHECK_NULL_VOID(layoutProperty);
3163     swiperStartIndex_ = std::clamp(swiperStartIndex_, 0, totalCount - 1);
3164     CHECK_NULL_VOID(IsValidIndex(swiperStartIndex_));
3165     auto index = swiperStartIndex_ + 1;
3166     if (index >= totalCount || index >= static_cast<int32_t>(tabBarStyles_.size())) {
3167         swiperStartIndex_--;
3168         index--;
3169         turnPageRate = 1.0f;
3170     }
3171     if (Negative(turnPageRate)) {
3172         turnPageRate = 0.0f;
3173     }
3174     CHECK_NULL_VOID(IsValidIndex(index));
3175     if (GreatOrEqual(turnPageRate, 1.0f)) {
3176         turnPageRate_ = 1.0f;
3177     } else if (LessOrEqual(turnPageRate, 0.0f)) {
3178         turnPageRate_ = 0.0f;
3179     } else {
3180         if (turnPageRate_ <= TEXT_COLOR_THREDHOLD && turnPageRate > TEXT_COLOR_THREDHOLD) {
3181             UpdateTextColorAndFontWeight(index);
3182         } else if (turnPageRate <= 1.0f - TEXT_COLOR_THREDHOLD && turnPageRate_ > 1.0f - TEXT_COLOR_THREDHOLD) {
3183             UpdateTextColorAndFontWeight(swiperStartIndex_);
3184         }
3185         turnPageRate_ = turnPageRate;
3186     }
3187     auto originalPaintRect = layoutProperty->GetIndicatorRect(swiperStartIndex_);
3188     auto targetPaintRect = layoutProperty->GetIndicatorRect(index);
3189     auto paintRectDiff = std::abs(targetPaintRect.GetX() + targetPaintRect.Width() / 2 - originalPaintRect.GetX() -
3190                                   originalPaintRect.Width() / 2);
3191 
3192     currentIndicatorOffset_ = originalPaintRect.GetX() + originalPaintRect.Width() / 2 + paintRectDiff * turnPageRate_;
3193     if (isRTL_) {
3194         auto originalPaintRect = layoutProperty->GetIndicatorRect(swiperStartIndex_ + 1);
3195         auto targetPaintRect = layoutProperty->GetIndicatorRect(swiperStartIndex_ >= 0 ? swiperStartIndex_ : 0);
3196         auto paintRectDiff = std::abs(targetPaintRect.GetX() + targetPaintRect.Width() / HALF_OF_WIDTH -
3197                                       originalPaintRect.GetX() - originalPaintRect.Width() / HALF_OF_WIDTH);
3198         currentIndicatorOffset_ =
3199             originalPaintRect.GetX() + originalPaintRect.Width() / HALF_OF_WIDTH + paintRectDiff * (1 - turnPageRate_);
3200     }
3201     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3202 }
3203 
InitTurnPageRateEvent()3204 void TabBarPattern::InitTurnPageRateEvent()
3205 {
3206     auto turnPageRateCallback = [weak = WeakClaim(this)](int32_t swipingIndex, float turnPageRate) {
3207         auto pattern = weak.Upgrade();
3208         if (pattern) {
3209             if (!pattern->CheckSwiperDisable() && pattern->axis_ == Axis::HORIZONTAL && pattern->isTouchingSwiper_) {
3210                 pattern->swiperStartIndex_ = swipingIndex;
3211                 pattern->ApplyTurnPageRateToIndicator(turnPageRate);
3212             } else if (!pattern->isAnimating_) {
3213                 pattern->turnPageRate_ = 0.0f;
3214             }
3215         }
3216     };
3217     swiperController_->SetTurnPageRateCallback(std::move(turnPageRateCallback));
3218 
3219     auto host = GetHost();
3220     CHECK_NULL_VOID(host);
3221     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3222     CHECK_NULL_VOID(tabsNode);
3223     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
3224     CHECK_NULL_VOID(swiperNode);
3225     auto eventHub = swiperNode->GetEventHub<SwiperEventHub>();
3226     CHECK_NULL_VOID(eventHub);
3227     if (!animationStartEvent_) {
3228         AnimationStartEvent animationStartEvent =
3229             [weak = WeakClaim(this)](int32_t index, int32_t targetIndex, const AnimationCallbackInfo& info) {
3230                 auto pattern = weak.Upgrade();
3231                 if (pattern) {
3232                     pattern->HandleBottomTabBarAnimation(targetIndex);
3233                 }
3234             };
3235         animationStartEvent_ = std::make_shared<AnimationStartEvent>(std::move(animationStartEvent));
3236         eventHub->AddAnimationStartEvent(animationStartEvent_);
3237     }
3238     if (!animationEndEvent_) {
3239         AnimationEndEvent animationEndEvent =
3240             [weak = WeakClaim(this)](int32_t index, const AnimationCallbackInfo& info) {
3241                 PerfMonitor::GetPerfMonitor()->End(PerfConstants::APP_TAB_SWITCH, true);
3242                 auto pattern = weak.Upgrade();
3243                 CHECK_NULL_VOID(pattern);
3244                 auto host = pattern->GetHost();
3245                 CHECK_NULL_VOID(host);
3246                 if (NearZero(pattern->turnPageRate_) || NearEqual(pattern->turnPageRate_, 1.0f)) {
3247                     pattern->isTouchingSwiper_ = false;
3248                     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
3249                 }
3250                 pattern->SetMaskAnimationExecuted(false);
3251             };
3252         animationEndEvent_ = std::make_shared<AnimationEndEvent>(std::move(animationEndEvent));
3253         eventHub->AddAnimationEndEvent(animationEndEvent_);
3254     }
3255 }
3256 
HandleBottomTabBarAnimation(int32_t index)3257 void TabBarPattern::HandleBottomTabBarAnimation(int32_t index)
3258 {
3259     auto preIndex = GetImageColorOnIndex().value_or(indicator_);
3260     if (preIndex < 0 || preIndex >= static_cast<int32_t>(tabBarStyles_.size())
3261         || index < 0 || index >= static_cast<int32_t>(tabBarStyles_.size())) {
3262         return;
3263     }
3264     if (tabBarStyles_[preIndex] != TabBarStyle::BOTTOMTABBATSTYLE &&
3265         tabBarStyles_[index] != TabBarStyle::BOTTOMTABBATSTYLE) {
3266         return;
3267     }
3268     if (preIndex != index) {
3269         auto host = GetHost();
3270         CHECK_NULL_VOID(host);
3271         auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3272         CHECK_NULL_VOID(tabsNode);
3273         auto tabsPattern = tabsNode->GetPattern<TabsPattern>();
3274         CHECK_NULL_VOID(tabsPattern);
3275         auto onChangeEvent = tabsPattern->GetChangeEvent();
3276         if (onChangeEvent) {
3277             (*onChangeEvent)(preIndex, index);
3278         }
3279         auto onIndexChangeEvent = tabsPattern->GetIndexChangeEvent();
3280         if (onIndexChangeEvent) {
3281             (*onIndexChangeEvent)(index);
3282         }
3283     }
3284     SetMaskAnimationExecuted(true);
3285 }
3286 
GetContentSize() const3287 SizeF TabBarPattern::GetContentSize() const
3288 {
3289     auto host = GetHost();
3290     CHECK_NULL_RETURN(host, SizeF(0.0f, 0.0f));
3291     auto geometryNode = host->GetGeometryNode();
3292     CHECK_NULL_RETURN(geometryNode, SizeF(0.0f, 0.0f));
3293     auto contentSize = geometryNode->GetPaddingSize();
3294     contentSize.MinusWidth(barGridMargin_ * 2); // 2 means left margin and right margin
3295     return contentSize;
3296 }
3297 
GetLeftPadding() const3298 float TabBarPattern::GetLeftPadding() const
3299 {
3300     auto host = GetHost();
3301     CHECK_NULL_RETURN(host, 0.0f);
3302     auto geometryNode = host->GetGeometryNode();
3303     CHECK_NULL_RETURN(geometryNode, 0.0f);
3304     if (!geometryNode->GetPadding()) {
3305         return barGridMargin_;
3306     }
3307     return geometryNode->GetPadding()->left.value_or(0.0f) + barGridMargin_;
3308 }
3309 
UpdateAnimationDuration()3310 void TabBarPattern::UpdateAnimationDuration()
3311 {
3312     if (animationDuration_.has_value() && animationDuration_.value() >= 0) {
3313         return;
3314     }
3315 
3316     std::optional<int32_t> duration;
3317     auto pipelineContext = GetContext();
3318     CHECK_NULL_VOID(pipelineContext);
3319     auto tabTheme = pipelineContext->GetTheme<TabTheme>();
3320     CHECK_NULL_VOID(tabTheme);
3321     auto host = GetHost();
3322     CHECK_NULL_VOID(host);
3323     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3324     CHECK_NULL_VOID(tabsNode);
3325     auto swiperNode = AceType::DynamicCast<FrameNode>(tabsNode->GetTabs());
3326     CHECK_NULL_VOID(swiperNode);
3327     auto swiperPaintProperty = swiperNode->GetPaintProperty<SwiperPaintProperty>();
3328     CHECK_NULL_VOID(swiperPaintProperty);
3329     duration = static_cast<int32_t>(tabTheme->GetTabContentAnimationDuration());
3330     if ((Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) &&
3331         std::count(tabBarStyles_.begin(), tabBarStyles_.end(), TabBarStyle::BOTTOMTABBATSTYLE)) ||
3332         (!animationDuration_.has_value() && Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN))) {
3333         duration = 0;
3334     }
3335     SetAnimationDuration(duration.value());
3336     swiperPaintProperty->UpdateDuration(duration.value());
3337 }
3338 
DumpAdvanceInfo()3339 void TabBarPattern::DumpAdvanceInfo()
3340 {
3341     isRTL_ ? DumpLog::GetInstance().AddDesc("isRTL:true") : DumpLog::GetInstance().AddDesc("isRTL:false");
3342     touching_ ? DumpLog::GetInstance().AddDesc("touching:true") : DumpLog::GetInstance().AddDesc("touching:false");
3343     isMaskAnimationByCreate_ ? DumpLog::GetInstance().AddDesc("isMaskAnimationByCreate:true")
3344                              : DumpLog::GetInstance().AddDesc("isMaskAnimationByCreate:false");
3345     animationDuration_.has_value()
3346         ? DumpLog::GetInstance().AddDesc("animationDuration:" + std::to_string(animationDuration_.value()))
3347         : DumpLog::GetInstance().AddDesc("animationDuration:null");
3348     isTouchingSwiper_ ? DumpLog::GetInstance().AddDesc("isTouchingSwiper:true")
3349                       : DumpLog::GetInstance().AddDesc("isTouchingSwiper:false");
3350     isAnimating_ ? DumpLog::GetInstance().AddDesc("isAnimating:true")
3351                  : DumpLog::GetInstance().AddDesc("isAnimating:false");
3352     changeByClick_ ? DumpLog::GetInstance().AddDesc("changeByClick:true")
3353                    : DumpLog::GetInstance().AddDesc("changeByClick:false");
3354     DumpLog::GetInstance().AddDesc("indicator:" + std::to_string(indicator_));
3355     DumpLog::GetInstance().AddDesc("swiperStartIndex:" + std::to_string(swiperStartIndex_));
3356     DumpLog::GetInstance().AddDesc("scrollMargin:" + std::to_string(scrollMargin_));
3357     std::string regionString = std::string("region:");
3358     for (auto item : gradientRegions_) {
3359         item ? regionString.append("true ") : regionString.append("false ");
3360     }
3361     DumpLog::GetInstance().AddDesc(regionString);
3362     switch (axis_) {
3363         case Axis::NONE: {
3364             DumpLog::GetInstance().AddDesc("Axis:NONE");
3365             break;
3366         }
3367         case Axis::HORIZONTAL: {
3368             DumpLog::GetInstance().AddDesc("Axis:HORIZONTAL");
3369             break;
3370         }
3371         case Axis::FREE: {
3372             DumpLog::GetInstance().AddDesc("Axis:FREE");
3373             break;
3374         }
3375         case Axis::VERTICAL: {
3376             DumpLog::GetInstance().AddDesc("Axis:VERTICAL");
3377             break;
3378         }
3379         default: {
3380             break;
3381         }
3382     }
3383 }
3384 
ContentWillChange(int32_t comingIndex)3385 bool TabBarPattern::ContentWillChange(int32_t comingIndex)
3386 {
3387     auto swiperPattern = GetSwiperPattern();
3388     CHECK_NULL_RETURN(swiperPattern, true);
3389     int32_t currentIndex = swiperPattern->GetCurrentIndex();
3390     return ContentWillChange(currentIndex, comingIndex);
3391 }
3392 
ContentWillChange(int32_t currentIndex,int32_t comingIndex)3393 bool TabBarPattern::ContentWillChange(int32_t currentIndex, int32_t comingIndex)
3394 {
3395     auto host = GetHost();
3396     CHECK_NULL_RETURN(host, true);
3397     auto tabsNode = AceType::DynamicCast<TabsNode>(host->GetParent());
3398     CHECK_NULL_RETURN(tabsNode, true);
3399     auto tabsPattern = tabsNode->GetPattern<TabsPattern>();
3400     CHECK_NULL_RETURN(tabsPattern, true);
3401     if (tabsPattern->GetInterceptStatus() && currentIndex != comingIndex) {
3402         auto ret = tabsPattern->OnContentWillChange(currentIndex, comingIndex);
3403         return ret.has_value() ? ret.value() : true;
3404     }
3405     return true;
3406 }
3407 
IsValidIndex(int32_t index)3408 bool TabBarPattern::IsValidIndex(int32_t index)
3409 {
3410     if (index < 0 || index >= static_cast<int32_t>(tabBarStyles_.size()) ||
3411         tabBarStyles_[index] != TabBarStyle::SUBTABBATSTYLE || index >= static_cast<int32_t>(selectedModes_.size()) ||
3412         selectedModes_[index] != SelectedMode::INDICATOR) {
3413         return false;
3414     }
3415     return true;
3416 }
3417 
GetLoopIndex(int32_t originalIndex) const3418 int32_t TabBarPattern::GetLoopIndex(int32_t originalIndex) const
3419 {
3420     auto host = GetHost();
3421     CHECK_NULL_RETURN(host, originalIndex);
3422     auto totalCount = host->TotalChildCount() - MASK_COUNT;
3423     if (totalCount <= 0) {
3424         return originalIndex;
3425     }
3426     return originalIndex % totalCount;
3427 }
3428 
SetRegionInfo(std::unique_ptr<JsonValue> & json)3429 void TabBarPattern::SetRegionInfo(std::unique_ptr<JsonValue>& json)
3430 {
3431     std::string regionString = "";
3432     for (auto item : gradientRegions_) {
3433         item ? regionString.append("true ") : regionString.append("false ");
3434     }
3435     json->Put("region", regionString.c_str());
3436     switch (axis_) {
3437         case Axis::NONE: {
3438             json->Put("Axis", "NONE");
3439             break;
3440         }
3441         case Axis::HORIZONTAL: {
3442             json->Put("Axis", "HORIZONTAL");
3443             break;
3444         }
3445         case Axis::FREE: {
3446             json->Put("Axis", "FREE");
3447             break;
3448         }
3449         case Axis::VERTICAL: {
3450             json->Put("Axis", "VERTICAL");
3451             break;
3452         }
3453         default: {
3454             break;
3455         }
3456     }
3457 }
3458 
DumpAdvanceInfo(std::unique_ptr<JsonValue> & json)3459 void TabBarPattern::DumpAdvanceInfo(std::unique_ptr<JsonValue>& json)
3460 {
3461     json->Put("isRTL", isRTL_);
3462     json->Put("touching", touching_);
3463     json->Put("isMaskAnimationByCreate", isMaskAnimationByCreate_);
3464     json->Put("animationDuration",
3465         animationDuration_.has_value() ? std::to_string(animationDuration_.value()).c_str() : "null");
3466     json->Put("isTouchingSwiper", isTouchingSwiper_);
3467     json->Put("isAnimating", isAnimating_);
3468     json->Put("changeByClick", changeByClick_);
3469     json->Put("indicator", indicator_);
3470     json->Put("swiperStartIndex", swiperStartIndex_);
3471     json->Put("scrollMargin", scrollMargin_);
3472     SetRegionInfo(json);
3473 }
3474 
AdjustTabBarInfo()3475 void TabBarPattern::AdjustTabBarInfo()
3476 {
3477     auto host = GetHost();
3478     CHECK_NULL_VOID(host);
3479     if (static_cast<int32_t>(tabBarItemIds_.size()) <= host->TotalChildCount() - MASK_COUNT) {
3480         return;
3481     }
3482 
3483     std::set<int32_t> retainedIndex;
3484     for (auto i = 0; i < static_cast<int32_t>(tabBarItemIds_.size()); i++) {
3485         auto itemId = tabBarItemIds_[i];
3486         if (host->GetChildIndexById(itemId) == -1) {
3487             continue;
3488         }
3489 
3490         retainedIndex.insert(i);
3491     }
3492 
3493     UpdateTabBarInfo<int32_t>(tabBarItemIds_, retainedIndex);
3494     UpdateTabBarInfo<SelectedMode>(selectedModes_, retainedIndex);
3495     UpdateTabBarInfo<IndicatorStyle>(indicatorStyles_, retainedIndex);
3496     UpdateTabBarInfo<TabBarStyle>(tabBarStyles_, retainedIndex);
3497     UpdateTabBarInfo<IconStyle>(iconStyles_, retainedIndex);
3498     UpdateTabBarInfo<TabBarSymbol>(symbolArray_, retainedIndex);
3499 }
3500 
InitFocusEvent()3501 void TabBarPattern::InitFocusEvent()
3502 {
3503     auto host = GetHost();
3504     CHECK_NULL_VOID(host);
3505     auto focusHub = host->GetFocusHub();
3506     CHECK_NULL_VOID(focusHub);
3507 
3508     auto focusTask = [weak = WeakClaim(this)]() {
3509         auto pattern = weak.Upgrade();
3510         CHECK_NULL_VOID(pattern);
3511         pattern->HandleFocusEvent();
3512     };
3513     focusHub->SetOnFocusInternal(focusTask);
3514 
3515     auto blurTask = [weak = WeakClaim(this)]() {
3516         auto pattern = weak.Upgrade();
3517         CHECK_NULL_VOID(pattern);
3518         pattern->HandleBlurEvent();
3519     };
3520     focusHub->SetOnBlurInternal(blurTask);
3521 
3522     auto getNextFocusNodeFunc = [weak = WeakClaim(this)](
3523                                     FocusReason reason, FocusIntension intension) -> RefPtr<FocusHub> {
3524         if (reason != FocusReason::FOCUS_TRAVEL) {
3525             return nullptr;
3526         }
3527         auto pattern = weak.Upgrade();
3528         CHECK_NULL_RETURN(pattern, nullptr);
3529         return pattern->GetCurrentFocusNode();
3530     };
3531     focusHub->SetOnGetNextFocusNodeFunc(getNextFocusNodeFunc);
3532     focusHub->SetAllowedLoop(false);
3533 }
3534 
AddIsFocusActiveUpdateEvent()3535 void TabBarPattern::AddIsFocusActiveUpdateEvent()
3536 {
3537     if (!isFocusActiveUpdateEvent_) {
3538         isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusActive) {
3539             auto pattern = weak.Upgrade();
3540             CHECK_NULL_VOID(pattern);
3541             pattern->UpdateFocusToSelectedNode(isFocusActive);
3542             pattern->SetTabBarFocusActive(isFocusActive);
3543             pattern->UpdateFocusTabBarPageState();
3544         };
3545     }
3546     auto host = GetHost();
3547     CHECK_NULL_VOID(host);
3548     auto pipeline = host->GetContext();
3549     CHECK_NULL_VOID(pipeline);
3550     pipeline->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
3551 }
3552 
RemoveIsFocusActiveUpdateEvent()3553 void TabBarPattern::RemoveIsFocusActiveUpdateEvent()
3554 {
3555     auto host = GetHost();
3556     CHECK_NULL_VOID(host);
3557     auto pipeline = host->GetContext();
3558     CHECK_NULL_VOID(pipeline);
3559     pipeline->RemoveIsFocusActiveUpdateEvent(GetHost());
3560 }
3561 
UpdateFocusToSelectedNode(bool isFocusActive)3562 void TabBarPattern::UpdateFocusToSelectedNode(bool isFocusActive)
3563 {
3564     if (!isFocusActive) {
3565         return;
3566     }
3567     auto childFocusNode = GetCurrentFocusNode();
3568     CHECK_NULL_VOID(childFocusNode);
3569     if (!childFocusNode->IsCurrentFocus()) {
3570         childFocusNode->RequestFocusImmediately();
3571     }
3572     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
3573     CHECK_NULL_VOID(layoutProperty);
3574     auto indicator = layoutProperty->GetIndicatorValue(0);
3575     FocusCurrentOffset(indicator);
3576 }
3577 
UpdateFocusTabBarPageState()3578 void TabBarPattern::UpdateFocusTabBarPageState()
3579 {
3580     if (tabBarStyle_ == TabBarStyle::SUBTABBATSTYLE) {
3581         UpdateSubTabBoard(indicator_);
3582         UpdateTextColorAndFontWeight(indicator_);
3583     }
3584 }
3585 
HandleFocusEvent()3586 void TabBarPattern::HandleFocusEvent()
3587 {
3588     auto context = GetContext();
3589     CHECK_NULL_VOID(context);
3590     AddIsFocusActiveUpdateEvent();
3591     if (context->GetIsFocusActive()) {
3592         SetTabBarFocusActive(true);
3593         UpdateFocusTabBarPageState();
3594         auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
3595         CHECK_NULL_VOID(layoutProperty);
3596         auto indicator = layoutProperty->GetIndicatorValue(0);
3597         FocusCurrentOffset(indicator);
3598     }
3599 }
3600 
HandleBlurEvent()3601 void TabBarPattern::HandleBlurEvent()
3602 {
3603     SetTabBarFocusActive(false);
3604     RemoveIsFocusActiveUpdateEvent();
3605     UpdateFocusTabBarPageState();
3606 }
3607 
UpdateSubTabFocusedTextColor(const RefPtr<TabTheme> & tabTheme,int32_t isFocusedItem,RefPtr<TextLayoutProperty> textLayoutProperty,int32_t index,bool isSelected)3608 void TabBarPattern::UpdateSubTabFocusedTextColor(const RefPtr<TabTheme>& tabTheme, int32_t isFocusedItem,
3609     RefPtr<TextLayoutProperty> textLayoutProperty, int32_t index, bool isSelected)
3610 {
3611     auto layoutProperty = GetLayoutProperty<TabBarLayoutProperty>();
3612     CHECK_NULL_VOID(layoutProperty);
3613     auto axis = layoutProperty->GetAxis().value_or(Axis::HORIZONTAL);
3614     bool isBoardWithBg = index < static_cast<int32_t>(selectedModes_.size()) &&
3615                         selectedModes_[index] == SelectedMode::BOARD && isSelected && axis == Axis::HORIZONTAL;
3616     bool isFocusWithBg = index < static_cast<int32_t>(tabBarStyles_.size()) && isFocusedItem && isTabBarFocusActive_ &&
3617                         tabBarStyles_[index] == TabBarStyle::SUBTABBATSTYLE;
3618     bool needUpdateTextColor = isBoardWithBg || isFocusWithBg;
3619     if (tabTheme->GetIsChangeFocusTextStyle() && needUpdateTextColor) {
3620         textLayoutProperty->UpdateTextColor(labelStyles_[index].selectedColor.has_value()
3621                                                 ? labelStyles_[index].selectedColor.value()
3622                                                 : tabTheme->GetSubTabTextFocusedColor());
3623     }
3624 }
3625 
InitTabBarProperties(const RefPtr<TabTheme> & tabTheme)3626 void TabBarPattern::InitTabBarProperties(const RefPtr<TabTheme>& tabTheme)
3627 {
3628     CHECK_NULL_VOID(tabTheme);
3629 
3630     tabBarItemHoverColor_ = tabTheme->GetSubTabBarHoverColor();
3631     tabBarItemFocusBgColor_ = tabTheme->GetTabBarFocusedColor();
3632     tabBarItemDefaultBgColor_ = Color::BLACK.BlendOpacity(0.0f);
3633 }
3634 
GetSubTabBarHoverColor(int32_t index) const3635 const Color& TabBarPattern::GetSubTabBarHoverColor(int32_t index) const
3636 {
3637     return (isTabBarFocusActive_ && index == focusIndicator_ && tabBarStyle_ == TabBarStyle::SUBTABBATSTYLE)
3638                ? tabBarItemFocusBgColor_
3639                : tabBarItemHoverColor_;
3640 }
3641 
UpdateSubTabBarItemStyles(const RefPtr<FrameNode> & columnNode,int32_t focusedColumnId,int32_t selectedColumnId,OHOS::Ace::Axis axis,int32_t index)3642 void TabBarPattern::UpdateSubTabBarItemStyles(const RefPtr<FrameNode>& columnNode, int32_t focusedColumnId,
3643     int32_t selectedColumnId, OHOS::Ace::Axis axis, int32_t index)
3644 {
3645     CHECK_NULL_VOID(columnNode);
3646     auto renderContext = columnNode->GetRenderContext();
3647     CHECK_NULL_VOID(renderContext);
3648     auto columnNodeId = columnNode->GetId();
3649     auto isSelected = columnNodeId == selectedColumnId;
3650     auto isColumnFocused = columnNodeId == focusedColumnId;
3651 
3652     Color itemColor;
3653     auto isFocusColorSet = tabBarItemFocusBgColor_ != Color::TRANSPARENT;
3654 
3655     if (!isFocusColorSet) {
3656         if (selectedModes_[index] == SelectedMode::BOARD && isSelected && axis == Axis::HORIZONTAL) {
3657             itemColor = indicatorStyles_[index].color;
3658         } else {
3659             itemColor = tabBarItemDefaultBgColor_;
3660         }
3661         renderContext->UpdateBackgroundColor(itemColor);
3662         return;
3663     }
3664     if (isTabBarFocusActive_) {
3665         itemColor = isColumnFocused ? tabBarItemFocusBgColor_ : tabBarItemDefaultBgColor_;
3666         renderContext->UpdateBackgroundColor(itemColor);
3667         return;
3668     }
3669     if (selectedModes_[index] == SelectedMode::BOARD && isSelected && axis == Axis::HORIZONTAL) {
3670         itemColor = tabBarItemFocusBgColor_;
3671     } else {
3672         itemColor = tabBarItemDefaultBgColor_;
3673     }
3674     renderContext->UpdateBackgroundColor(itemColor);
3675 }
3676 
GetColumnId(int32_t & selectedColumnId,int32_t & focusedColumnId,int32_t indicator) const3677 void TabBarPattern::GetColumnId(int32_t& selectedColumnId, int32_t& focusedColumnId, int32_t indicator) const
3678 {
3679     auto tabBarNode = GetHost();
3680     CHECK_NULL_VOID(tabBarNode);
3681     auto columnNode = DynamicCast<FrameNode>(tabBarNode->GetChildAtIndex(indicator));
3682     CHECK_NULL_VOID(columnNode);
3683     selectedColumnId = columnNode->GetId();
3684     auto focusedColumnNode = DynamicCast<FrameNode>(tabBarNode->GetChildAtIndex(focusIndicator_));
3685     CHECK_NULL_VOID(focusedColumnNode);
3686     focusedColumnId = focusedColumnNode->GetId();
3687 }
3688 
3689 template<typename T>
UpdateTabBarInfo(std::vector<T> & info,const std::set<int32_t> & retainedIndex)3690 void TabBarPattern::UpdateTabBarInfo(std::vector<T>& info, const std::set<int32_t>& retainedIndex)
3691 {
3692     std::vector<T> newInfo;
3693     for (auto index : retainedIndex) {
3694         if (index >= static_cast<int32_t>(info.size())) {
3695             continue;
3696         }
3697 
3698         newInfo.emplace_back(info[index]);
3699     }
3700 
3701     std::swap(newInfo, info);
3702 }
3703 } // namespace OHOS::Ace::NG
3704