Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change iOS SetNeedsLayout propagation mechanism #26629

Merged

Conversation

albyrock87
Copy link
Contributor

@albyrock87 albyrock87 commented Dec 14, 2024

Description of Change

I've been asked to split #25664 into separate PR.

This is the first piece which aims to change the way we propagate SetNeedsLayout by doing that only when MAUI commands.

  • The bug I'm solving with this PR is caused by this unwanted propagation when SetNeedsLayout is being invoked by iOS
  • Moving the propagation to InvalidateMeasure will enable third party libraries to remove the workarounds they've done to propagate SetNeedsLayout and don't care about propagation anymore

This also enables us to receive a SetNeedsLayout in TemplatedCell which will allow us to resize the cell without relaying on MeasureInvalidated cross platform event propagation.
There will be a follow-up PR to tackle this.

Issues Fixed

Fixes #24996

@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Dec 14, 2024
@albyrock87 albyrock87 force-pushed the ios-set-neesd-layout-propagation-mapper branch from 2ad0ab2 to 5b5e4b9 Compare December 14, 2024 11:54
@PureWeen
Copy link
Member

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen
Copy link
Member

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@jfversluis jfversluis added the area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter label Dec 16, 2024
Copy link
Member

@rmarinho rmarinho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@samhouts samhouts requested a review from Copilot December 17, 2024 18:00
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 8 out of 23 changed files in this pull request and generated 1 comment.

Files not reviewed (15)
  • src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt: Language not supported
  • src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt: Language not supported
  • src/Controls/tests/TestCases.HostApp/Issues/Issue24996.xaml: Language not supported
  • src/Core/src/Platform/iOS/LayoutView.cs: Evaluated as low risk
  • src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs: Evaluated as low risk
  • src/Controls/tests/DeviceTests/Elements/CarouselView/CarouselViewTests.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/PageViewController.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/MauiView.cs: Evaluated as low risk
  • src/Core/src/Handlers/Layout/LayoutHandler.iOS.cs: Evaluated as low risk
  • src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/MauiScrollView.cs: Evaluated as low risk
  • src/Controls/src/Core/Handlers/Items/iOS/MauiCollectionView.cs: Evaluated as low risk
  • src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/IMauiPlatformView.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/PageView.cs: Evaluated as low risk

@samhouts samhouts requested a review from Copilot December 17, 2024 18:05
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 8 out of 23 changed files in this pull request and generated no comments.

Files not reviewed (15)
  • src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt: Language not supported
  • src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt: Language not supported
  • src/Controls/tests/TestCases.HostApp/Issues/Issue24996.xaml: Language not supported
  • src/Core/src/Platform/iOS/LayoutView.cs: Evaluated as low risk
  • src/Controls/tests/DeviceTests/Elements/CarouselView/CarouselViewTests.cs: Evaluated as low risk
  • src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/PageViewController.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/MauiView.cs: Evaluated as low risk
  • src/Core/src/Handlers/Layout/LayoutHandler.iOS.cs: Evaluated as low risk
  • src/Controls/src/Core/Compatibility/Handlers/iOS/VisualElementRenderer.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/MauiScrollView.cs: Evaluated as low risk
  • src/Controls/src/Core/Handlers/Items/iOS/MauiCollectionView.cs: Evaluated as low risk
  • src/Core/src/Handlers/ScrollView/ScrollViewHandler.iOS.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/PageView.cs: Evaluated as low risk
  • src/Core/src/Platform/iOS/IMauiPlatformView.cs: Evaluated as low risk
Comments suppressed due to low confidence (3)

src/Controls/tests/TestCases.HostApp/Issues/Issue26629.cs:22

  • [nitpick] The variable name 'i' is ambiguous. It should be renamed to 'labelCounter'.
var i = 0;

src/Core/src/Platform/iOS/ViewExtensions.cs:288

  • Ensure that the new behavior introduced by the InvalidateMeasure method is covered by tests.
public static void InvalidateMeasure(this UIView platformView, IView view)

src/Core/src/Platform/iOS/ViewExtensions.cs:308

  • Ensure that the new behavior introduced by the InvalidateAncestorsMeasures method is covered by tests.
internal static void InvalidateAncestorsMeasures(this UIView child)

@albyrock87 albyrock87 force-pushed the ios-set-neesd-layout-propagation-mapper branch from 21dd5bf to e861dc4 Compare December 17, 2024 19:38
@rmarinho
Copy link
Member

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@PureWeen PureWeen self-assigned this Dec 18, 2024
@PureWeen PureWeen added this to the .NET 9 SR3 milestone Dec 18, 2024
@albyrock87 albyrock87 force-pushed the ios-set-neesd-layout-propagation-mapper branch 6 times, most recently from 1967ec8 to ce2cc4b Compare December 19, 2024 14:27
@rmarinho
Copy link
Member

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Contributor

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

@mattleibow
Copy link
Member

Is this image change expected? Also, the after still looks wrong because if the image button has no height, then why is the image small? The image was always small, but now it is less weird with all the space. Still wrong, but better wrong?

image

@albyrock87
Copy link
Contributor Author

Is this image change expected? Also, the after still looks wrong because if the image button has no height, then why is the image small? The image was always small, but now it is less weird with all the space. Still wrong, but better wrong?

@mattleibow this is the Windows one, so it looked correct to me.

image

The image has no height, true, but it also has WidthRequest="50" where the default aspect is AspectFit, so that's why the image is small, because it keeps the original aspect while matching the requested width.

mattleibow
mattleibow previously approved these changes Mar 3, 2025
Copy link
Member

@PureWeen PureWeen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • For the PageView type can we just do something possibly a little silly until we address the "potential improvement" comment? Like, just add an internal property on MauiView that can be used to do the same thing? My worry here is that in some cases users are probably inheriting from ContentView and providing their own type for the PageHandler. So, if we just set something inside the SetVirtualView part of the PageHandler that enables the same short circuiting that won't break anyone. If we're going to change the type here, we'd probably want to do that through a new handler.

  • I wonder if we can just get rid of the InvalidateMeasure on IPlatformMeasureInvalidationController

    • AFAICT the only types that benefits from this are ScrollView/CollectionView. Everyone else just calls SetNeedsLayout from this
    • for ScrollView can the code that's in there just move to an override of SetNeedsLayout ?
    • For collectionView we could just special case it inside "InvalidateAncestorsMeasures" for now since it is the only outlier. I would just be curious as we implement the code for optimizing propagation if this also becomes somewhat unnecessary. We're already special casing UIScrollView inside InvalidateAncestorsMeasures so once we evolve this solution a bit then we can hopefully shed these special cases a bit?

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@albyrock87 albyrock87 force-pushed the ios-set-neesd-layout-propagation-mapper branch from aef3942 to 28e4710 Compare March 4, 2025 10:14
@albyrock87
Copy link
Contributor Author

@PureWeen

just set something inside the SetVirtualView part of the PageHandler that enables the same short circuiting

As per our conversation, this has been implemented through a new internal bool IsPage { get; set; } property on ContentView. PageView has been removed.

I wonder if we can just get rid of the InvalidateMeasure on IPlatformMeasureInvalidationController

I don't think we can do this, let me explain.

for ScrollView can the code that's in there just move to an override of SetNeedsLayout ?

UIScrollView natively triggers SetNeedsLayout a lot of times when the user scrolls, that doesn't mean we have to invalidate our measure constraint cache, so we need to differentiate between MAUI invalidation and native invalidation which is the exact root cause of #24996 issue.

AFAICT the only types that benefits from this are ScrollView/CollectionView. Everyone else just calls SetNeedsLayout from this

This made me think, so I've looked again at MauiView and you're right: I'm just calling SetNeedsLayout(), but now I think I should move InvalidateCacheConstraints from SetNeedsLayout to InvalidateMeasure so that's what I've done in the last commit.
Now I'm curious to see if this passes the tests: I have many failures locally, even on main so I can't verify them all.

@PureWeen
Copy link
Member

PureWeen commented Mar 4, 2025

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

Copy link
Member

@mattleibow mattleibow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 2 questions.

Comment on lines 90 to 91
double widthRatio = constrainedWidth / contentWidth;
double heightRatio = constrainedHeight / contentHeight;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To confirm what I am thinking, this is the size used to determine the size of the control, so you are including the padding in here because iOS does not have a [padding concept?

But, as @PureWeen mentioned - should it be used in the aspect ratio calculations? Maybe it should be added on after the size calculations? For example, if I have a landscape image, but massive padding on top/bottom that makes it become a portrait scale. Will it cause issues with stretch?

Maybe I am thinking wrong here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, I've updated the algorithm as follows:

  • Remove padding from constraints
  • Compute desired size on reduced constraints
  • Add padding back

@PureWeen
Copy link
Member

PureWeen commented Mar 4, 2025

/azp run

Copy link

Azure Pipelines successfully started running 3 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter community ✨ Community Contribution p/0 Work that we can't release without
Projects
Status: Done
7 participants