diff --git a/.gitee/CODEOWNERS b/.gitee/CODEOWNERS index edad7b5bd95ee27bbe542005be1a25acc16c68b4..a430d91b7aab8d6608c19b0d157702aee8974479 100644 --- a/.gitee/CODEOWNERS +++ b/.gitee/CODEOWNERS @@ -2477,6 +2477,7 @@ frameworks/core/components_ng/pattern/lazy_layout/ @arkuiscroll frameworks/core/components_ng/pattern/linear_indicator/ @arkuiscroll frameworks/core/components_ng/pattern/linear_layout/ @arkuilayout frameworks/core/components_ng/pattern/linear_split/ @arkuilayout +frameworks/core/components_ng/pattern/arc_list/ @arkuiscroll frameworks/core/components_ng/pattern/list/ @arkuiscroll frameworks/core/components_ng/pattern/loading_progress/ @arkui_image frameworks/core/components_ng/pattern/marquee/ @huawei_g_five @@ -3271,6 +3272,7 @@ test/unittest/core/pattern/indexer/ @arkuiscroll test/unittest/core/pattern/lazy_layout/ @arkuiscroll test/unittest/core/pattern/linear_layout/ @arkuilayout test/unittest/core/pattern/linear_split/ @arkuilayout +test/unittest/core/pattern/arc_list/ @arkuiscroll test/unittest/core/pattern/list/ @arkuiscroll test/unittest/core/pattern/loading_progress/ @arkui_image test/unittest/core/pattern/marquee/ @huawei_g_five diff --git a/frameworks/core/components_ng/pattern/arc_list/arc_list_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/arc_list/arc_list_layout_algorithm.cpp index 1d30a36ad45ef591c9a84b4a4274bc95229739de..59494c47ec62b4f25128a3c60d8a61512bf94cf8 100755 --- a/frameworks/core/components_ng/pattern/arc_list/arc_list_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/arc_list/arc_list_layout_algorithm.cpp @@ -461,7 +461,7 @@ void ArcListLayoutAlgorithm::LayoutHeader(LayoutWrapper* layoutWrapper, const Of float itemDispStartPos = info.startPos + info.offsetY - itemDeltaHeight / FLOAT_TWO; startHeaderPos_ = itemDispStartPos - headerMainSize_; if (CheckNeedUpdateHeaderOffset(layoutWrapper)) { - headerOffset_ = GreatNotEqual(startHeaderPos_, HEADER_DIST) ? startHeaderPos_ - HEADER_DIST : 0.0f; + headerOffset_ = CalculateHeaderOffset(layoutWrapper, info); } startHeaderPos_ -= headerOffset_; if (GreatNotEqual(startHeaderPos_, -TRANSPARENCY_DIST)) { @@ -499,6 +499,29 @@ void ArcListLayoutAlgorithm::LayoutHeader(LayoutWrapper* layoutWrapper, const Of } } +float ArcListLayoutAlgorithm::CalculateHeaderOffset(LayoutWrapper* layoutWrapper, const ListItemInfo& info) +{ + auto firstItemWrapper = GetListItem(layoutWrapper, 0); + if (firstItemWrapper) { + // Calculate the start position of the first item in the middle of the ArcList. + auto listItemLayoutProperty = + AceType::DynamicCast(firstItemWrapper->GetLayoutProperty()); + auto autoScale = listItemLayoutProperty ? listItemLayoutProperty->GetAutoScale().value_or(true) : true; + auto scale = autoScale ? GetNearScale(0.0f) : 1.0f; + auto itemHeight = (info.endPos - info.startPos) * scale; + auto itemDispStartPosInCenter = (contentMainSize_ - itemHeight) / FLOAT_TWO; + + // Calculate the start position of the header when the first item in the middle of the ArcList. + auto headerStartPosInTop = itemDispStartPosInCenter - headerMainSize_; + headerStartPosInTop = + GreatNotEqual(headerStartPosInTop, HEADER_DIST) ? HEADER_DIST : headerStartPosInTop; + + return itemDispStartPosInCenter - (headerStartPosInTop + headerMainSize_); + } else { + return GreatNotEqual(startHeaderPos_, HEADER_DIST) ? startHeaderPos_ - HEADER_DIST : 0.0f; + } +} + bool ArcListLayoutAlgorithm::CheckNeedUpdateHeaderOffset(LayoutWrapper* layoutWrapper) { auto host = layoutWrapper->GetHostNode(); diff --git a/frameworks/core/components_ng/pattern/arc_list/arc_list_layout_algorithm.h b/frameworks/core/components_ng/pattern/arc_list/arc_list_layout_algorithm.h index 4b14170cd0e49f852bbdfb69b9ad88b34a235f89..9a8729da613094d2079e403a67222fa65db7908f 100755 --- a/frameworks/core/components_ng/pattern/arc_list/arc_list_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/arc_list/arc_list_layout_algorithm.h @@ -116,6 +116,7 @@ private: void MeasureHeader(LayoutWrapper* layoutWrapper) override; void LayoutHeader(LayoutWrapper* layoutWrapper, const OffsetF& paddingOffset, float crossSize) override; + float CalculateHeaderOffset(LayoutWrapper* layoutWrapper, const ListItemInfo& info); bool CheckNeedUpdateHeaderOffset(LayoutWrapper* layoutWrapper); void UpdateZIndex(const RefPtr& layoutWrapper); void CalcContentOffset(const RefPtr& property) override diff --git a/test/unittest/core/pattern/arc_list/arc_list_layout_test_ng.cpp b/test/unittest/core/pattern/arc_list/arc_list_layout_test_ng.cpp index 07ed4ed34d2b533ce44142e6d44dad99812bb867..b6b38138a5c4924db7c8658adf7a38bc3d843429 100755 --- a/test/unittest/core/pattern/arc_list/arc_list_layout_test_ng.cpp +++ b/test/unittest/core/pattern/arc_list/arc_list_layout_test_ng.cpp @@ -976,6 +976,65 @@ HWTEST_F(ArcListLayoutTestNg, LayoutHeader003, TestSize.Level1) EXPECT_EQ(algorithm->headerIndex_, 0); } +/** + * @tc.name: LayoutHeader004 + * @tc.desc: Test ArcListLayoutAlgorithm::LayoutHeader when the height of first item changed + * @tc.type: FUNC + */ +HWTEST_F(ArcListLayoutTestNg, LayoutHeader004, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create list with header. + */ + ListModelNG model = CreateList(); + auto headerSize = 50.0f; + auto column = CreateColumn([headerSize](ColumnModelNG model) { + ViewAbstract::SetWidth(CalcLength(headerSize)); + ViewAbstract::SetHeight(CalcLength(headerSize)); + }); + model.SetHeader(column); + CreateListItems(DEFAULT_ITEM_COUNT); + CreateDone(); + + /** + * @tc.steps: step2. Flush ui task. + * @tc.expected: 1. The start position of the header is 40.0f. 2. The distance between the header and the first item + * is greater than 0, that is, the value of headerOffset_ is greater than 0. + */ + FlushUITasks(frameNode_); + auto headerDist = 40.0f; + auto headerOffset = (LIST_HEIGHT - ITEM_HEIGHT * 1.08f) / 2.0f - headerDist - headerSize; + EXPECT_EQ(pattern_->startHeaderPos_, headerDist); + EXPECT_EQ(pattern_->headerOffset_, headerOffset); + EXPECT_EQ(pattern_->oldFirstItemSize_, ITEM_HEIGHT); + EXPECT_EQ(pattern_->oldHeaderSize_, headerSize); + + /** + * @tc.steps: step3. Scroll list. + * @tc.expected: The value of headerOffset_ unchanged. + */ + ScrollTo(100); + EXPECT_EQ(pattern_->headerOffset_, headerOffset); + + /** + * @tc.steps: step4. Decrease the height of the first item. + * @tc.expected: The value of headerOffset_ becomes larger. + */ + auto firstItem = AceType::DynamicCast(frameNode_->GetChildAtIndex(1)); + ViewAbstract::SetHeight(AceType::RawPtr(firstItem), CalcLength(ITEM_HEIGHT / 2.0f)); + FlushUITasks(frameNode_); + EXPECT_GT(pattern_->headerOffset_, headerOffset); + EXPECT_EQ(pattern_->oldFirstItemSize_, ITEM_HEIGHT / 2.0f); + + /** + * @tc.steps: step5. Scroll list. + * @tc.expected: 1. The start position of the header is 40.0f. 2. The value of headerOffset_ unchanged. + */ + ScrollTo(-200); + EXPECT_EQ(pattern_->startHeaderPos_, headerDist); + EXPECT_GT(pattern_->headerOffset_, headerOffset); +} + /** * @tc.name: CreateLayoutAlgorithm001 * @tc.desc: Test ArcListPattern::CreateLayoutAlgorithm