1 /*
2 * Copyright (c) 2021-2022 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/list/render_list_item.h"
17
18 #include "base/log/dump_log.h"
19 #include "base/utils/system_properties.h"
20 #include "core/common/frontend.h"
21 #include "core/common/vibrator/vibrator_proxy.h"
22 #include "core/components/box/render_box.h"
23 #include "core/components/flex/render_flex.h"
24 #include "core/components/list/render_list.h"
25 #include "core/components/list/render_list_item_group.h"
26 #include "core/components/list/tv_interactive_effect.h"
27 #ifdef WEARABLE_PRODUCT
28 #include "core/components/list/watch_interactive_effect.h"
29 #endif
30 #include "core/components/proxy/render_item_proxy.h"
31
32 namespace OHOS::Ace {
33 namespace {
34
35 const double HALF_SIZE = 0.5;
36 const double ITEM_DISTANCE_BASE = 76.0;
37 const double ITEM_DEFAULT_SCALE = 1.0;
38 const double ITEM_ZERO = 0.0;
39 const double ITEM_SCALE_BASE = 1.12;
40 const double ITEM_OPACITY_BASE = 1.0;
41 const double ITEM_RATIO = -0.34; // 0.78 - 1.12 // 0.66 - 1.0
42 const double DISTANCE_EPSILON = 1.0;
43 constexpr int32_t MIN_COMPATITABLE_VERSION = 5;
44 const double WATCH_SIZE = 466.0;
45
46 #ifdef WEARABLE_PRODUCT
47 const std::string& VIBRATOR_TYPE_WATCH_CROWN_STRENGTH1 = "watchhaptic.crown.strength1";
48 #endif
49
50 } // namespace
51
RenderListItem()52 RenderListItem::RenderListItem()
53 {
54 Initialize();
55 }
56
Initialize()57 void RenderListItem::Initialize()
58 {
59 clickRecognizer_ = AceType::MakeRefPtr<ClickRecognizer>();
60 clickRecognizer_->SetOnClick([weakItem = AceType::WeakClaim(this)](const ClickInfo&) {
61 auto item = weakItem.Upgrade();
62 if (item) {
63 item->HandleClicked();
64 }
65 });
66 touchRecognizer_ = AceType::MakeRefPtr<RawRecognizer>();
67 touchRecognizer_->SetOnTouchDown([weakItem = AceType::WeakClaim(this)](const TouchEventInfo&) {
68 auto item = weakItem.Upgrade();
69 if (item && item->GetSupportClick()) {
70 item->PlayPressDownAnimation();
71 }
72 });
73 touchRecognizer_->SetOnTouchUp([weakItem = AceType::WeakClaim(this)](const TouchEventInfo&) {
74 auto item = weakItem.Upgrade();
75 if (item && item->GetSupportClick()) {
76 item->PlayPressUpAnimation();
77 }
78 });
79 touchRecognizer_->SetOnTouchCancel([weakItem = AceType::WeakClaim(this)](const TouchEventInfo&) {
80 auto item = weakItem.Upgrade();
81 if (item && item->GetSupportClick()) {
82 item->PlayPressUpAnimation();
83 }
84 });
85 }
86
PerformLayout()87 void RenderListItem::PerformLayout()
88 {
89 if (!GetChildren().empty()) {
90 auto child = GetChildren().front();
91 auto context = context_.Upgrade();
92 if (NeedDivider() && context && context->GetIsDeclarative()) {
93 auto layoutParam = GetLayoutParam();
94 auto maxSize = layoutParam.GetMaxSize();
95 auto dividerSize = IsListVertical() ? Size(0.0, NormalizeToPx(dividerHeight_))
96 : Size(NormalizeToPx(dividerHeight_), 0.0);
97 maxSize = maxSize - dividerSize;
98 layoutParam.SetMaxSize(maxSize);
99 child->Layout(layoutParam);
100 } else {
101 child->Layout(GetLayoutParam());
102 }
103 child->SetPosition(Offset::Zero());
104 if (NeedDivider()) {
105 auto dividerSize = IsListVertical() ? Size(0.0, NormalizeToPx(dividerHeight_))
106 : Size(NormalizeToPx(dividerHeight_), 0.0);
107 SetLayoutSize(dividerSize + child->GetLayoutSize());
108 } else {
109 SetLayoutSize(child->GetLayoutSize());
110 }
111 // update focus animation size
112 focusAnimationRRect_.SetRect(Rect(Offset(0, 0), GetPaintSize() * TV_ITEM_SCALE));
113
114 if (SystemProperties::GetDeviceType() == DeviceType::WATCH) {
115 CalculateScaleFactorOnWatch();
116 }
117 }
118 }
119
CalculateScaleFactorOnWatch()120 void RenderListItem::CalculateScaleFactorOnWatch()
121 {
122 if (isTitle_) {
123 return;
124 }
125
126 auto context = GetContext().Upgrade();
127 const static int32_t PLATFORM_VERSION_FIVE = 5;
128 if (context && context->GetMinPlatformVersion() <= PLATFORM_VERSION_FIVE) {
129 Offset itemCenter = GetGlobalOffset() + GetLayoutSize() * HALF_SIZE;
130 double scale = ITEM_DEFAULT_SCALE;
131 double viewScale = ITEM_DEFAULT_SCALE;
132 auto pipelineContext = context_.Upgrade();
133 if (pipelineContext) {
134 scale = pipelineContext->GetDipScale();
135 viewScale = pipelineContext->GetViewScale();
136 }
137 if (NearZero(scale) || NearZero(viewScale)) {
138 LOGE("pipeline parameter is invalid");
139 return;
140 }
141 auto distance = std::abs(itemCenter.GetY() - WATCH_SIZE / viewScale * HALF_SIZE);
142 auto ratio = std::pow(distance, SQUARE) * ITEM_RATIO / std::pow(ITEM_DISTANCE_BASE * scale, SQUARE);
143 scaleFactor_ = std::max(ITEM_ZERO, ratio + ITEM_SCALE_BASE);
144 opacityFactor_ = std::max(ITEM_ZERO, ratio + ITEM_OPACITY_BASE);
145 } else {
146 auto renderList = GetRenderList();
147 if (!renderList) {
148 LOGE("Can not find parent render list");
149 return;
150 }
151
152 double itemSize = renderList->IsVertical() ? GetLayoutSize().Height() : GetLayoutSize().Width();
153 double itemCenter = GetPositionInList() + renderList->GetListPosition() + itemSize * HALF_SIZE;
154 double scale = ITEM_DEFAULT_SCALE;
155 auto pipelineContext = context_.Upgrade();
156 if (pipelineContext) {
157 scale = pipelineContext->GetDipScale();
158 }
159 if (NearZero(scale)) {
160 LOGE("Pipeline parameter is invalid");
161 return;
162 }
163 double viewPort = renderList->IsVertical() ? viewPort_.Height() : viewPort_.Width();
164 auto distance = std::abs(itemCenter - viewPort * HALF_SIZE);
165 if (NearZero(distance, DISTANCE_EPSILON)) {
166 distance = 0.0;
167 }
168 auto ratio = std::pow(distance, SQUARE) * ITEM_RATIO / std::pow(ITEM_DISTANCE_BASE * scale, SQUARE);
169 scaleFactor_ = std::max(ITEM_ZERO, ratio + ITEM_SCALE_BASE);
170 opacityFactor_ = std::max(ITEM_ZERO, ratio + ITEM_OPACITY_BASE);
171 }
172 }
173
Update(const RefPtr<Component> & component)174 void RenderListItem::Update(const RefPtr<Component>& component)
175 {
176 itemComponent_ = component;
177 auto item = AceType::DynamicCast<ListItemComponent>(component);
178 if (item) {
179 type_ = item->GetType();
180 index_ = item->GetIndex();
181 columnSpan_ = item->GetColumnSpan();
182 op_ = item->GetOperation();
183 flags_ = item->GetFlags();
184 // update focus animation color
185 focusAnimationColor_ = item->GetFocusAnimationColor();
186 // update focus animation corner radius
187 focusAnimationRRect_.SetCorner({ item->GetTopLeftRadius(), item->GetTopRightRadius(),
188 item->GetBottomRightRadius(), item->GetBottomLeftRadius() });
189
190 needVibrate_ = item->NeedVibrate();
191 auto context = context_.Upgrade();
192 if (needVibrate_ && !vibrator_ && context) {
193 vibrator_ = VibratorProxy::GetInstance().GetVibrator(context->GetTaskExecutor());
194 }
195
196 rotationVibrate_ = item->IsRotationVibrate();
197 if (rotationVibrate_ && !vibrator_ && context) {
198 vibrator_ = VibratorProxy::GetInstance().GetVibrator(context->GetTaskExecutor());
199 }
200
201 supportScale_ = item->GetSupportScale();
202 supportOpacity_ = item->GetSupportOpacity();
203 supportClick_ = item->GetSupportClick();
204 isTitle_ = item->IsTitle();
205 sticky_ = item->GetSticky();
206 stickyMode_ = item->GetStickyMode();
207 clickColor_ = item->GetClickColor();
208 selfAlign_ = item->GetAlignSelf();
209 Dimension radius = item->GetStickyRadius();
210 if (radius.IsValid()) {
211 stickyRadius_ = context ? context->NormalizeToPx(radius) : stickyRadius_;
212 }
213
214 if (!primary_ && item->GetPrimary()) {
215 NotifyGroupPrimaryChange();
216 }
217 SetPrimary(item->GetPrimary());
218
219 // list divider
220 needDivider_ = item->NeedDivider();
221 isActive_ = item->IsActive();
222 dividerLength_ = item->GetDividerLength();
223 dividerHeight_ = item->GetDividerHeight();
224 dividerOrigin_ = item->GetDividerOrigin();
225 dividerColor_ = item->GetDividerColor();
226 auto onClickId = item->GetClickEventId();
227 clickEvent_ = AceAsyncEvent<void()>::Create(onClickId, GetContext());
228 clickRecognizer_->SetUseCatchMode(true);
229 if (!onClickId.GetCatchMode()) {
230 static const int32_t bubbleModeVersion = 6;
231 auto pipeline = context_.Upgrade();
232 if (pipeline && pipeline->GetMinPlatformVersion() >= bubbleModeVersion) {
233 clickRecognizer_->SetUseCatchMode(false);
234 return;
235 }
236 }
237 stickyEvent_ = AceAsyncEvent<void(const std::string&)>::Create(item->GetStickyEventId(), GetContext());
238 transitionEffect_ = item->GetTransitionEffect();
239 UpdateAccessibilityAttr();
240 MarkNeedLayout();
241 }
242 }
243
NotifyGroupPrimaryChange()244 void RenderListItem::NotifyGroupPrimaryChange()
245 {
246 auto parent = GetParent().Upgrade();
247 while (parent) {
248 auto group = AceType::DynamicCast<RenderListItemGroup>(parent);
249 if (group) {
250 group->ItemPrimaryChange(GetIndex());
251 break;
252 }
253 parent = parent->GetParent().Upgrade();
254 }
255 }
256
GetPositionInList() const257 double RenderListItem::GetPositionInList() const
258 {
259 RefPtr<RenderNode> parentNode = GetParent().Upgrade();
260 while (parentNode) {
261 RefPtr<RenderList> listNode = AceType::DynamicCast<RenderList>(parentNode);
262 if (listNode) {
263 return listNode->GetItemPosition(index_);
264 }
265 parentNode = parentNode->GetParent().Upgrade();
266 }
267 return 0.0;
268 }
269
IsItemCenter(bool isVertical,Size viewport)270 bool RenderListItem::IsItemCenter(bool isVertical, Size viewport)
271 {
272 auto parent = GetParent().Upgrade();
273 if (!parent) {
274 return false;
275 }
276 Size itemSize = GetLayoutSize();
277 Offset itemPosition = parent->GetPosition();
278 double size = isVertical ? itemSize.Height() : itemSize.Width();
279 double position = isVertical ? itemPosition.GetY() : itemPosition.GetX();
280 double center = (isVertical ? viewport.Height() : viewport.Width()) / 2.0;
281 return center > position && center < (position + size);
282 }
283
ResetFocusEffect()284 void RenderListItem::ResetFocusEffect()
285 {
286 #ifdef WEARABLE_PRODUCT
287 if (SystemProperties::GetDeviceType() == DeviceType::WATCH) {
288 focusController_ = AceType::MakeRefPtr<WatchInteractiveEffect>(GetContext());
289 #else
290 if (SystemProperties::GetDeviceType() == DeviceType::TV) {
291 focusController_ = AceType::MakeRefPtr<TVInteractiveEffect>(GetContext());
292 #endif
293 } else {
294 focusController_ = AceType::MakeRefPtr<InteractiveEffect>(GetContext());
295 }
296 focusController_->Initialize(GetThemeManager());
297 focusController_->SetItemNode(AceType::WeakClaim(this));
298 auto listNode = GetRenderList();
299 if (listNode) {
300 auto weakList = WeakPtr<RenderList>(listNode);
301 focusController_->SetListNode(weakList);
302 }
303 }
304
305 void RenderListItem::HandleItemEffect(bool isFromRotate)
306 {
307 if (!focusController_) {
308 ResetFocusEffect();
309 }
310
311 if (currentState_ != lastState_) {
312 #ifdef WEARABLE_PRODUCT
313 if (needVibrate_ && lastState_ == ItemState::NEARBY && currentState_ == ItemState::FOCUS && vibrator_) {
314 vibrator_->Vibrate(VIBRATOR_TYPE_WATCH_CROWN_STRENGTH1);
315 }
316 if (rotationVibrate_ && isFromRotate && vibrator_) {
317 vibrator_->Vibrate(VIBRATOR_TYPE_WATCH_CROWN_STRENGTH1);
318 }
319 #endif
320 lastState_ = currentState_;
321 if (currentState_ != ItemState::NONE && currentState_ != ItemState::CLICK) {
322 focusController_->ShowAnimation(currentState_);
323 } else {
324 // invalid focus
325 }
326 }
327 MarkNeedRender();
328 }
329
330 void RenderListItem::HandleClicked()
331 {
332 if (clickEvent_) {
333 clickEvent_();
334 }
335
336 if (primary_ && clicked_) {
337 clicked_();
338 }
339 }
340
341 void RenderListItem::PlayPressDownAnimation()
342 {
343 if (!focusController_) {
344 ResetFocusEffect();
345 }
346 pressAnimation_ = true;
347 focusController_->TouchDownAnimation();
348 }
349
350 void RenderListItem::PlayPressUpAnimation()
351 {
352 if (!focusController_) {
353 ResetFocusEffect();
354 }
355 pressAnimation_ = false;
356 focusController_->TouchUpAnimation();
357 }
358
359 void RenderListItem::OnCancelPressAnimation()
360 {
361 if (!pressAnimation_) {
362 return;
363 }
364 if (!focusController_) {
365 ResetFocusEffect();
366 }
367 focusController_->CancelTouchAnimation();
368 }
369
370 void RenderListItem::HandleStickyEvent(bool sticky)
371 {
372 std::string state = sticky ? "true" : "false";
373 std::string param = std::string(R"("sticky",{"state":)").append(state).append("},null");
374 if (stickyEvent_) {
375 stickyEvent_(param);
376 }
377 }
378
379 void RenderListItem::OnTouchTestHit(
380 const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
381 {
382 if (!GetVisible() && !GetClonedBySticky()) {
383 return;
384 }
385 // supportClick means show click effect
386 bool supportClick = supportClick_;
387 auto pipeline = context_.Upgrade();
388 if (pipeline && pipeline->GetMinPlatformVersion() > MIN_COMPATITABLE_VERSION) {
389 supportClick = true;
390 }
391 if ((!touchRecognizer_) || (!clickRecognizer_) || (!supportClick)) {
392 return;
393 }
394 touchRecognizer_->SetCoordinateOffset(coordinateOffset);
395 clickRecognizer_->SetCoordinateOffset(coordinateOffset);
396 result.emplace_back(touchRecognizer_);
397 result.emplace_back(clickRecognizer_);
398 }
399
400 void RenderListItem::UpdateItemFocusRect(double scale)
401 {
402 focusAnimationRRect_.SetRect(Rect(Offset(0.0, 0.0), GetPaintSize() * scale));
403 }
404
405 void RenderListItem::HandleFocusEvent(bool focus, bool isInGroup)
406 {
407 if (SystemProperties::GetDeviceType() == DeviceType::WATCH) {
408 return;
409 }
410 focused_ = focus;
411
412 ShowFocusAnimation(focus, Rect(0.0, 0.0, 0.0, 0.0));
413
414 if (focus) {
415 ChangeStatus(RenderStatus::FOCUS);
416 currentState_ = ItemState::FOCUS;
417 if (isInGroup) {
418 HandleItemEffect();
419 return;
420 }
421 RefPtr<RenderNode> parentNode = GetParent().Upgrade();
422 while (parentNode) {
423 RefPtr<RenderList> listNode = AceType::DynamicCast<RenderList>(parentNode);
424 if (listNode) {
425 listNode->ListItemFocused(index_);
426 break;
427 }
428 parentNode = parentNode->GetParent().Upgrade();
429 }
430 } else {
431 ChangeStatus(RenderStatus::BLUR);
432 currentState_ = ItemState::BLUR;
433 }
434 HandleItemEffect();
435 }
436
437 Offset RenderListItem::GetPaintOffset() const
438 {
439 auto globalOffset = GetGlobalOffset();
440 auto layoutSize = GetLayoutSize(); // size include margin
441 auto paintSize = GetPaintSize(); // size exclude margin
442 auto margin = GetMarginInPx();
443 if (layoutSize > paintSize) {
444 globalOffset.SetX(globalOffset.GetX() + margin.LeftPx());
445 globalOffset.SetY(globalOffset.GetY() + margin.TopPx());
446 }
447 return globalOffset;
448 }
449
450 EdgePx RenderListItem::GetMarginInPx() const
451 {
452 EdgePx marginInPx;
453 auto children = GetChildren();
454 if (children.empty()) {
455 return marginInPx;
456 }
457
458 auto child = children.front();
459 while (child) {
460 auto box = AceType::DynamicCast<RenderBoxBase>(child);
461 if (box) {
462 auto boxChildren = box->GetChildren();
463 if (boxChildren.empty()) {
464 break;
465 }
466 auto boxChild = boxChildren.front();
467 if (boxChild && AceType::DynamicCast<RenderFlex>(boxChild)) {
468 marginInPx = box->GetMargin();
469 break;
470 }
471 }
472 children = child->GetChildren();
473 if (children.empty()) {
474 break;
475 }
476 child = children.front();
477 }
478 return marginInPx;
479 }
480
481 Size RenderListItem::GetPaintSize() const
482 {
483 Size size = GetLayoutSize();
484 auto margin = GetMarginInPx();
485 return size - margin.GetLayoutSize();
486 }
487
488 Border RenderListItem::GetFocusBorder() const
489 {
490 Border border;
491 border.SetTopRightRadius(focusAnimationRRect_.GetCorner().topRightRadius);
492 border.SetTopLeftRadius(focusAnimationRRect_.GetCorner().topLeftRadius);
493 border.SetBottomLeftRadius(focusAnimationRRect_.GetCorner().bottomLeftRadius);
494 border.SetBottomRightRadius(focusAnimationRRect_.GetCorner().bottomRightRadius);
495 return border;
496 }
497
498 void RenderListItem::ShowFocusAnimation(bool focus, const Rect& listRect, double scale)
499 {
500 // paint focus animation
501 auto context = context_.Upgrade();
502 if (!context) {
503 LOGE("[Focus]Pipeline context is nullptr");
504 return;
505 }
506
507 if (focus) {
508 Size size = GetPaintSize();
509 auto globalOffset = GetPaintOffset() + (size * (DEFAULT_SCALE - scale) * HALF_SIZE);
510 if (listRect.IsValid()) {
511 context->ShowFocusAnimation(focusAnimationRRect_, focusAnimationColor_, globalOffset, listRect);
512 context->ShowShadow(focusAnimationRRect_, globalOffset);
513 } else {
514 context->ShowFocusAnimation(focusAnimationRRect_, focusAnimationColor_, globalOffset);
515 context->ShowShadow(focusAnimationRRect_, globalOffset);
516 }
517 } else {
518 context->CancelFocusAnimation();
519 context->CancelShadow();
520 }
521 }
522
523 void RenderListItem::UpdateAccessibilityAttr()
524 {
525 auto refPtr = accessibilityNode_.Upgrade();
526 if (!refPtr) {
527 return;
528 }
529
530 refPtr->SetClickableState(true);
531 refPtr->SetActionClickImpl([weakItem = AceType::WeakClaim(this)]() {
532 auto item = weakItem.Upgrade();
533 if (item) {
534 LOGI("Trigger ActionClick by Accessibility(%{public}d).", item->index_);
535 item->HandleClicked();
536 item->OnGroupClicked();
537 }
538 });
539
540 refPtr->SetFocusableState(true);
541 refPtr->SetActionFocusImpl([weakItem = AceType::WeakClaim(this)]() {
542 auto item = weakItem.Upgrade();
543 if (item) {
544 LOGI("Trigger ActionFocus by Accessibility(%{public}d).", item->index_);
545 item->MoveToViewPort();
546 }
547 });
548 refPtr->AddSupportAction(AceAction::ACTION_ACCESSIBILITY_FOCUS);
549 }
550
551 void RenderListItem::OnGroupClicked()
552 {
553 if (!primary_ || !curPrimary_) {
554 return; // Only trigger group click when current item is primary.
555 }
556 RefPtr<RenderNode> parent = GetParent().Upgrade();
557 while (parent) {
558 RefPtr<RenderListItemGroup> group = AceType::DynamicCast<RenderListItemGroup>(parent);
559 if (group) {
560 return group->HandleClicked();
561 }
562 parent = parent->GetParent().Upgrade();
563 }
564 }
565
566 void RenderListItem::MoveToViewPort()
567 {
568 RefPtr<RenderNode> parentNode = GetParent().Upgrade();
569 while (parentNode) {
570 RefPtr<RenderList> listNode = AceType::DynamicCast<RenderList>(parentNode);
571 if (listNode) {
572 return listNode->MoveItemToViewPort(GetPositionInList());
573 }
574 parentNode = parentNode->GetParent().Upgrade();
575 }
576 }
577
578 RefPtr<RenderList> RenderListItem::GetRenderList() const
579 {
580 auto parent = GetParent().Upgrade();
581 while (parent) {
582 auto parentNode = AceType::DynamicCast<RenderList>(parent);
583 if (parentNode) {
584 return parentNode;
585 }
586 parent = parent->GetParent().Upgrade();
587 }
588 return nullptr;
589 }
590
591 bool RenderListItem::NeedDivider()
592 {
593 return needDivider_ && !IsLastItem();
594 }
595
596 bool RenderListItem::IsLastItem()
597 {
598 auto renderList = GetRenderList();
599 if (renderList) {
600 int32_t maxCount = renderList->GetMaxCount();
601 if (GetIndex() == maxCount - 1) {
602 return true;
603 }
604 }
605 return false;
606 }
607
608 bool RenderListItem::IsListVertical()
609 {
610 auto renderList = GetRenderList();
611 if (renderList) {
612 FlexDirection listDirection = renderList->GetDirection();
613 return listDirection == FlexDirection::COLUMN || listDirection == FlexDirection::COLUMN_REVERSE;
614 }
615 return true;
616 }
617
618 void RenderListItem::Dump()
619 {
620 DumpLog::GetInstance().AddDesc(std::string("index: ").append(std::to_string(GetIndex())));
621 }
622
623 void RenderListItem::RunCardTransitionAnimation(double shiftHeight)
624 {
625 auto renderList = GetRenderList();
626 if (!renderList) {
627 LOGE("list render is null");
628 return;
629 }
630 makeCardTransition_ = true;
631 renderList->SetMakeCardTransition(makeCardTransition_);
632 if (transitionEffect_ == TransitionEffect::UNFOLD) {
633 renderList->SetShiftHeight(shiftHeight);
634 } else {
635 renderList->SetShiftHeight(0.0);
636 }
637 renderList->MarkNeedRender();
638 }
639
640 void RenderListItem::StopCardTransitionAnimation()
641 {
642 makeCardTransition_ = false;
643 auto renderList = GetRenderList();
644 if (renderList) {
645 renderList->SetMakeCardTransition(makeCardTransition_);
646 renderList->SetShiftHeight(0.0);
647 renderList->MarkNeedRender();
648 }
649 }
650
651 RRect RenderListItem::GetRRect() const
652 {
653 auto child = GetFirstChild();
654 while (child) {
655 auto childNode = AceType::DynamicCast<RenderBox>(child);
656 if (childNode) {
657 auto margin = childNode->GetMargin();
658 auto rrect = RRect(Rect(childNode->GetGlobalOffset() + margin.GetOffset(),
659 childNode->GetLayoutSize() - margin.GetLayoutSize()));
660 if (childNode->GetBackDecoration()) {
661 auto border = childNode->GetBackDecoration()->GetBorder();
662 rrect.SetCorner({ border.TopLeftRadius(), border.TopRightRadius(),
663 border.BottomLeftRadius(), border.BottomRightRadius() });
664 }
665 return rrect;
666 }
667 child = child->GetFirstChild();
668 }
669 return RRect();
670 }
671
672 } // namespace OHOS::Ace
673