From 113154856d7697844c5cf5255081d62a19fd5c71 Mon Sep 17 00:00:00 2001 From: hw_ljz Date: Wed, 20 Aug 2025 17:14:01 +0800 Subject: [PATCH] fix flex, relativeContainer percentSensitive bug Signed-off-by: hw_ljz --- .../components_ng/layout/layout_algorithm.cpp | 16 +++ .../components_ng/layout/layout_algorithm.h | 2 + .../pattern/flex/flex_layout_algorithm.cpp | 14 ++ .../pattern/flex/flex_layout_algorithm.h | 5 +- .../pattern/flex/flex_layout_property.h | 12 -- .../pattern/flex/wrap_layout_algorithm.cpp | 18 ++- .../pattern/flex/wrap_layout_algorithm.h | 4 +- .../linear_layout/linear_layout_property.h | 5 - .../core/pattern/flex/flex_new_test_ng.cpp | 127 +++++++++++++----- 9 files changed, 146 insertions(+), 57 deletions(-) diff --git a/frameworks/core/components_ng/layout/layout_algorithm.cpp b/frameworks/core/components_ng/layout/layout_algorithm.cpp index b41e2c2a794..a2b2ff0783f 100644 --- a/frameworks/core/components_ng/layout/layout_algorithm.cpp +++ b/frameworks/core/components_ng/layout/layout_algorithm.cpp @@ -93,4 +93,20 @@ void LayoutAlgorithmWrapper::SetAbsLayoutAlgorithm(const RefPtrGetLayoutAlgorithm(); + CHECK_NULL_VOID(layoutAlgorithmWrapper); + layoutAlgorithmWrapper->SetPercentHeight(value); +} + +void LayoutAlgorithm::SetWidthPercentSensitive(LayoutWrapper *layoutWrapper, bool value) +{ + CHECK_NULL_VOID(layoutWrapper); + auto layoutAlgorithmWrapper = layoutWrapper->GetLayoutAlgorithm(); + CHECK_NULL_VOID(layoutAlgorithmWrapper); + layoutAlgorithmWrapper->SetPercentWidth(value); +} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/layout/layout_algorithm.h b/frameworks/core/components_ng/layout/layout_algorithm.h index ec754b2723f..5d6b93523aa 100644 --- a/frameworks/core/components_ng/layout/layout_algorithm.h +++ b/frameworks/core/components_ng/layout/layout_algorithm.h @@ -46,6 +46,8 @@ public: OnReset(); } + void SetHeightPercentSensitive(LayoutWrapper *layoutWrapper, bool value = true); + void SetWidthPercentSensitive(LayoutWrapper *layoutWrapper, bool value = true); virtual std::optional MeasureContent( const LayoutConstraintF& /*contentConstraint*/, LayoutWrapper* /*layoutWrapper*/) { diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp index 7a6c62283b0..e8046cea7be 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp @@ -206,6 +206,7 @@ void FlexLayoutAlgorithm::CheckBaselineProperties(const RefPtr& l */ void FlexLayoutAlgorithm::InitFlexProperties(LayoutWrapper* layoutWrapper) { + isUsingPercentReference_ = false; mainAxisSize_ = 0.0f; crossAxisSize_ = 0.0f; allocatedSize_ = 0.0f; @@ -590,6 +591,7 @@ void FlexLayoutAlgorithm::MeasureAndCleanMagicNodes( * If the total main axis size of the element is larger than the main axis size of Flex, the lower priority * element will be deleted. */ + UpdatePercentSensitive(containerLayoutWrapper); auto firstLoopIter = FirstMeasureInWeightMode(); SecondMeasureInWeightMode(firstLoopIter); FinalMeasureInWeightMode(); @@ -614,6 +616,7 @@ void FlexLayoutAlgorithm::MeasureAndCleanMagicNodes( CheckSizeValidity(childLayoutWrapper); CheckBaselineProperties(childLayoutWrapper); if (!isInfiniteLayout_ || GreatNotEqual(MainAxisMinValue(containerLayoutWrapper), 0.0f)) { + UpdatePercentSensitive(containerLayoutWrapper); UpdateFlexProperties(flexItemProperties, childLayoutWrapper); } secondaryMeasureList_.emplace_back(child); @@ -995,6 +998,16 @@ void FlexLayoutAlgorithm::CheckMainAxisSizeAuto( } } +void FlexLayoutAlgorithm::UpdatePercentSensitive(LayoutWrapper* layoutWrapper) +{ + CHECK_EQUAL_VOID(isUsingPercentReference_, false); + if (IsHorizontal(direction_)) { + SetWidthPercentSensitive(layoutWrapper); + return; + } + SetHeightPercentSensitive(layoutWrapper); +} + void FlexLayoutAlgorithm::SetInitMainAxisSize(LayoutWrapper* layoutWrapper) { auto layoutProperty = layoutWrapper->GetLayoutProperty(); @@ -1019,6 +1032,7 @@ void FlexLayoutAlgorithm::SetInitMainAxisSize(LayoutWrapper* layoutWrapper) IsHorizontal(direction_) ? (mainAxisInf ? layoutConstraint->percentReference.Width() : layoutConstraint->maxSize.Width()) : (mainAxisInf ? layoutConstraint->percentReference.Height() : layoutConstraint->maxSize.Height()); + isUsingPercentReference_ = mainAxisInf; } isInfiniteLayout_ = isLinearLayoutFeature_; } diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h index c08101eb031..ef609af7af0 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -142,7 +142,7 @@ private: break; } } - + void UpdatePercentSensitive(LayoutWrapper* layoutWrapper); OptionalSizeF realSize_; float mainAxisSize_ = 0.0f; float crossAxisSize_ = 0.0f; @@ -169,6 +169,7 @@ private: bool selfAdaptive_ = false; TextDirection textDir_ = TextDirection::LTR; bool childrenHasAlignSelfBaseLine_ = false; + bool isUsingPercentReference_ = false; ACE_DISALLOW_COPY_AND_MOVE(FlexLayoutAlgorithm); }; diff --git a/frameworks/core/components_ng/pattern/flex/flex_layout_property.h b/frameworks/core/components_ng/pattern/flex/flex_layout_property.h index 6586b4df239..cbcd8819933 100644 --- a/frameworks/core/components_ng/pattern/flex/flex_layout_property.h +++ b/frameworks/core/components_ng/pattern/flex/flex_layout_property.h @@ -60,18 +60,6 @@ public: ResetWrapLayoutAttribute(); } - std::pair GetPercentSensitive() override - { - auto flexDirection = GetFlexDirection().value_or(FlexDirection::ROW); - auto res = LayoutProperty::GetPercentSensitive(); - if (flexDirection == FlexDirection::ROW || flexDirection == FlexDirection::ROW_REVERSE) { - res.first = true; - } else if (flexDirection == FlexDirection::COLUMN || flexDirection == FlexDirection::COLUMN_REVERSE) { - res.second = true; - } - return res; - } - ACE_DEFINE_PROPERTY_GROUP(FlexLayoutAttribute, FlexLayoutAttribute); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FlexLayoutAttribute, FlexDirection, FlexDirection, PROPERTY_UPDATE_MEASURE); ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FlexLayoutAttribute, MainAxisAlign, FlexAlign, PROPERTY_UPDATE_MEASURE); diff --git a/frameworks/core/components_ng/pattern/flex/wrap_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/flex/wrap_layout_algorithm.cpp index 464bfbd8316..e2613eb5ed6 100644 --- a/frameworks/core/components_ng/pattern/flex/wrap_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/flex/wrap_layout_algorithm.cpp @@ -52,13 +52,15 @@ bool IsColumnReverse(WrapDirection direction) } } -void WrapLayoutAlgorithm::UpdatePercentSensitive(LayoutWrapper *layoutWrapper) +void WrapLayoutAlgorithm::UpdatePercentSensitive( + LayoutWrapper *layoutWrapper, bool usingWidthPercent, bool usingHeightPercent) { - CHECK_NULL_VOID(layoutWrapper && layoutWrapper->GetHostTag() == V2::FLEX_ETS_TAG); - auto layoutAlgorithmWrapper = layoutWrapper->GetLayoutAlgorithm(); - CHECK_NULL_VOID(layoutAlgorithmWrapper); - layoutAlgorithmWrapper->SetPercentWidth(true); - layoutAlgorithmWrapper->SetPercentHeight(true); + if (usingWidthPercent) { + SetWidthPercentSensitive(layoutWrapper); + } + if (usingHeightPercent) { + SetHeightPercentSensitive(layoutWrapper); + } } void WrapLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) @@ -72,7 +74,6 @@ void WrapLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) outOfLayoutChildren_.clear(); auto flexProp = AceType::DynamicCast(layoutWrapper->GetLayoutProperty()); CHECK_NULL_VOID(flexProp); - UpdatePercentSensitive(layoutWrapper); direction_ = flexProp->GetWrapDirection().value_or(WrapDirection::HORIZONTAL); // alignment for alignContent, alignment when cross axis has extra space alignment_ = flexProp->GetAlignment().value_or(WrapAlignment::START); @@ -89,6 +90,7 @@ void WrapLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper) isRightDirection_ = textDir_ == TextDirection::RTL; isColumnReverse_ = IsColumnReverse(direction_); PerformLayoutInitialize(flexProp); + UpdatePercentSensitive(layoutWrapper, isWidthPercentSensitive_, isHeightPercentSensitive_); totalMainLength_ = 0.0f; totalCrossLength_ = 0.0f; auto realMaxSize = GetLeftSize(0.0f, mainLengthLimit_, crossLengthLimit_); @@ -284,6 +286,8 @@ void WrapLayoutAlgorithm::PerformLayoutInitialize(const RefPtr& mainLengthLimit_ = std::min(constraint->maxSize.Height(), constraint->percentReference.Height()); crossLengthLimit_ = std::min(constraint->maxSize.Width(), constraint->percentReference.Width()); } + isWidthPercentSensitive_ = GreaterOrEqualToInfinity(constraint->maxSize.Width()); + isHeightPercentSensitive_ = GreaterOrEqualToInfinity(constraint->maxSize.Height()); } else { if (isHorizontal_) { mainLengthLimit_ = constraint->maxSize.Width(); diff --git a/frameworks/core/components_ng/pattern/flex/wrap_layout_algorithm.h b/frameworks/core/components_ng/pattern/flex/wrap_layout_algorithm.h index 6349a1c1cce..508ea7a1a61 100644 --- a/frameworks/core/components_ng/pattern/flex/wrap_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/flex/wrap_layout_algorithm.h @@ -110,7 +110,7 @@ private: void CalcFlexGrowLayout( const RefPtr& itemWrapper, const FlexItemProperties& flexItemProperties, float remainSpace); - void UpdatePercentSensitive(LayoutWrapper *layoutWrapper); + void UpdatePercentSensitive(LayoutWrapper *layoutWrapper, bool usingWidthPercent, bool usingHeightPercent); WrapDirection direction_ = WrapDirection::VERTICAL; WrapAlignment alignment_ = WrapAlignment::START; WrapAlignment mainAlignment_ = WrapAlignment::START; @@ -133,6 +133,8 @@ private: OffsetF frameOffset_; bool hasIdealWidth_ = false; bool hasIdealHeight_ = false; + bool isHeightPercentSensitive_ = false; + bool isWidthPercentSensitive_ = false; // Should be clear after Layout. std::list contentList_; diff --git a/frameworks/core/components_ng/pattern/linear_layout/linear_layout_property.h b/frameworks/core/components_ng/pattern/linear_layout/linear_layout_property.h index 8c49fd034ad..88cd5d337c3 100644 --- a/frameworks/core/components_ng/pattern/linear_layout/linear_layout_property.h +++ b/frameworks/core/components_ng/pattern/linear_layout/linear_layout_property.h @@ -60,11 +60,6 @@ public: return isVertical_; } - std::pair GetPercentSensitive() override - { - return LayoutProperty::GetPercentSensitive(); - } - void ToJsonValue(std::unique_ptr& json, const InspectorFilter& filter) const override { LayoutProperty::ToJsonValue(json, filter); diff --git a/test/unittest/core/pattern/flex/flex_new_test_ng.cpp b/test/unittest/core/pattern/flex/flex_new_test_ng.cpp index d53617303ee..1c59773da63 100644 --- a/test/unittest/core/pattern/flex/flex_new_test_ng.cpp +++ b/test/unittest/core/pattern/flex/flex_new_test_ng.cpp @@ -29,7 +29,6 @@ const float RK356_WIDTH = 720.0f; const float RK356_HEIGHT = 1136.0f; const SizeF CONTAINER_SIZE(RK356_WIDTH, RK356_HEIGHT); const float ZERO = 0.0f; -const float INFINITY_NUM = 1000000.0f; const OffsetF OFFSET_TOP_LEFT = OffsetF(ZERO, ZERO); } // namespace class FlexNewTestNG : public FlexBaseTestNG { @@ -801,35 +800,6 @@ HWTEST_F(FlexNewTestNG, CalcItemCrossAxisOffset002, TestSize.Level1) EXPECT_EQ(ret, 10.0f); } -/** - * @tc.name: FlexInfinityPercentHeight001 - * @tc.desc: test flex ignoreLayoutSafeArea - * @tc.type: FUNC - */ -HWTEST_F(FlexNewTestNG, FlexInfinityPercentHeight001, TestSize.Level1) -{ - auto frameNode = CreateColumn([this](ColumnModelNG model) {}); - auto flexColumn = CreateFlexRow([this](FlexModelNG model) { model.SetDirection(FlexDirection::COLUMN); }); - auto flexRow = CreateFlexRow([this](FlexModelNG model) { model.SetDirection(FlexDirection::ROW); }); - LayoutConstraintF parentConstraint { .percentReference { RK356_WIDTH, RK356_HEIGHT }, - .maxSize { RK356_WIDTH, INFINITY_NUM } }; - auto layoutProperty = frameNode->GetLayoutProperty(); - layoutProperty->UpdateLayoutConstraint(parentConstraint); - auto res = layoutProperty->GetPercentSensitive(); - EXPECT_EQ(res.first, false); - EXPECT_EQ(res.second, false); - auto flexColumnLayoutProperty = flexColumn->GetLayoutProperty(); - flexColumnLayoutProperty->UpdateLayoutConstraint(parentConstraint); - auto flexColumnSensitive = flexColumnLayoutProperty->GetPercentSensitive(); - EXPECT_EQ(flexColumnSensitive.first, false); - EXPECT_EQ(flexColumnSensitive.second, true); - auto flexRowLayoutProperty = flexRow->GetLayoutProperty(); - flexRowLayoutProperty->UpdateLayoutConstraint(parentConstraint); - auto flexRowSensitive = flexRowLayoutProperty->GetPercentSensitive(); - EXPECT_EQ(flexRowSensitive.first, true); - EXPECT_EQ(flexRowSensitive.second, false); -} - /** * @tc.name: FlexIgnoreLayoutSafeArea001 * @tc.desc: test flex ignoreLayoutSafeArea @@ -1490,4 +1460,101 @@ HWTEST_F(FlexNewTestNG, FlexWrapTest001, TestSize.Level1) EXPECT_EQ(size2, SizeF(162.5f, 100.0f)); EXPECT_EQ(offset2, OffsetF(162.5f, 0.0f)); } + +/** + * @tc.name: UpdatePercentSensitiveTest + * @tc.desc: test UpdatePercentSensitive + * @tc.type: FUNC + */ +HWTEST_F(FlexNewTestNG, UpdatePercentSensitiveTest, TestSize.Level1) +{ + auto flexNode = CreateFlexRow([this](FlexModelNG model) {}); + FlexLayoutAlgorithm algorithm; + algorithm.UpdatePercentSensitive(Referenced::RawPtr(flexNode)); + auto layoutAlgorithmWrapper = flexNode->GetLayoutAlgorithm(); + /** + * @tc.expected: widthPercent_ == false, heightPercent_ == false + */ + EXPECT_FALSE(layoutAlgorithmWrapper->GetPercentHeight()); + EXPECT_FALSE(layoutAlgorithmWrapper->GetPercentWidth()); + algorithm.isUsingPercentReference_ = true; + algorithm.UpdatePercentSensitive(Referenced::RawPtr(flexNode)); + /** + * @tc.expected: isUsingPercentReference_ == true means flexAlgorithm use percentReference + * to initialize horizontal mainAxis size so widthPercent_ == true + */ + EXPECT_FALSE(layoutAlgorithmWrapper->GetPercentHeight()); + EXPECT_TRUE(layoutAlgorithmWrapper->GetPercentWidth()); + algorithm.direction_ = FlexDirection::COLUMN; + algorithm.UpdatePercentSensitive(Referenced::RawPtr(flexNode)); + /** + * @tc.expected: isUsingPercentReference_ == true means flexAlgorithm use percentReference + * to initialize horizontal mainAxis size so heightPercent_ == true + */ + EXPECT_TRUE(layoutAlgorithmWrapper->GetPercentHeight()); +} + +/** + * @tc.name: SetInitMainAxisSizeTest + * @tc.desc: test SetInitMainAxisSize set isUsingPercentReference_ correctly + * test flex layout algorithm update percentSensitive correctly + * @tc.type: FUNC + */ +HWTEST_F(FlexNewTestNG, SetInitMainAxisSizeTest, TestSize.Level1) +{ + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + pipeline->SetMinPlatformVersion(12); + auto flexNode = CreateFlexRow([this](FlexModelNG model) {}); + auto layoutAlgorithmWrapper = flexNode->GetLayoutAlgorithm(); + FlexLayoutAlgorithm algorithm; + algorithm.direction_ = FlexDirection::COLUMN; + algorithm.mainAxisSize_ = -1.0f; + LayoutConstraintF constraint; + flexNode->GetLayoutProperty()->UpdateLayoutConstraint(constraint); + /** + * @tc.expected: use percentReference to initialize mainAxis size, isUsingPercentReference_ == true + */ + algorithm.SetInitMainAxisSize(Referenced::RawPtr(flexNode)); + algorithm.isLinearLayoutFeature_ = false; + EXPECT_TRUE(algorithm.isUsingPercentReference_); + /** + * @tc.expected: when totalFlexWeight_ > 0, set percentSensitiveHeight to true + */ + algorithm.totalFlexWeight_ = 10; + FlexItemProperties flexItemProperty; + algorithm.MeasureAndCleanMagicNodes(Referenced::RawPtr(flexNode), flexItemProperty); + EXPECT_TRUE(layoutAlgorithmWrapper->GetPercentHeight()); + /** + * @tc.expected: when isInfiniteLayout_ is false, percentSensitiveHeight should be false + */ + algorithm.totalFlexWeight_= 0; + algorithm.maxDisplayPriority_= 10; + algorithm.isInfiniteLayout_ = false; + layoutAlgorithmWrapper->SetPercentHeight(false); + algorithm.MeasureAndCleanMagicNodes(Referenced::RawPtr(flexNode), flexItemProperty); + EXPECT_FALSE(layoutAlgorithmWrapper->GetPercentHeight()); +} + +/** + * @tc.name: MeasureAndCleanMagicNodesTest + * @tc.desc: test flex layout algorithm update percentSensitive correctly + * @tc.type: FUNC + */ +HWTEST_F(FlexNewTestNG, MeasureAndCleanMagicNodesTest, TestSize.Level1) +{ + auto flexNode = CreateFlexRow([this](FlexModelNG model) { + CreateText(u"text1", [this](TextModelNG model) { + }); + }); + LayoutConstraintF constraint; + constraint.minSize.SetHeight(100.f); + auto layoutProperty = flexNode->GetLayoutProperty(); + layoutProperty->UpdateLayoutConstraint(constraint); + layoutProperty->UpdateContentConstraint(); + FlexLayoutAlgorithm algorithm; + algorithm.Measure(Referenced::RawPtr(flexNode)); + auto layoutAlgorithmWrapper = flexNode->GetLayoutAlgorithm(); + EXPECT_FALSE(layoutAlgorithmWrapper->GetPercentWidth()); +} } // namespace OHOS::Ace::NG \ No newline at end of file -- Gitee