Skip to content

Support sizing of UIKit interop views using Auto Layout#2797

Merged
Vendula Švastalová (svastven) merged 19 commits into
jb-mainfrom
svastven/sizing-interop-views-in-compose
Mar 4, 2026
Merged

Support sizing of UIKit interop views using Auto Layout#2797
Vendula Švastalová (svastven) merged 19 commits into
jb-mainfrom
svastven/sizing-interop-views-in-compose

Conversation

@svastven

@svastven Vendula Švastalová (svastven) commented Feb 26, 2026

Copy link
Copy Markdown

Adds support for sizing of UIKit interop views using Auto Layout.

Introduces

  • UIKitInteropElementLayout
    • handles embedding of UIKit containers and userComponent view into hierarchy
  • UIKitInteropElementMeasurePolicy
    • provides MeasurePolicy for the Compose node hosting the UIKit interop view
    • handles calculation of the UIKit userComponent fitting size and providing it to Compose layout
    • handles re-measure requests from UIKitInteropRemeasureRequester
  • UIKitInteropRemeasureRequester
    • requestRemeasure() provides a way to request remeasurement of UIKitView or UIKitViewController based on fitting size changes of the given interopView
  • Modifier.remeasureRequester
    • provide a way to request remeasurement of UIKit interop node

Fixes CMP-9123 iOS support intrinsic sizing of interop elements - UIView with NSLayoutConstraints

Testing

Adds iOS instrumented tests covering interop view behavior:

  • wrap-content sizing from UIKit fixed constraints
  • Compose fixed size modifiers (size, fillMaxSize) vs UIKit constraints
  • multiline UILabel fitting in combinations (fixed width / fixed height / no explicit size)
  • UIStackView fitting
  • aspect-ratio constraint fitting
  • explicit remeasure flow using UIKitInteropRemeasureRequester (constraint constant change, text change)
  • remeasureRequester lifecycle (binding/unbinding when interop node is added/removed)

This should be tested by QA

Release Notes

Features - iOS

  • Support automatic sizing for Auto Layout–based views together with supporting explicit remeasurement via rememberUIKitInteropRemeasureRequester() + Modifier.remeasureRequester(...) with UIKitInteropRemeasureRequester.requestRemeasure() for propagating UIKit-side size changes to Compose.

@MatkovIvan Ivan Matkov (MatkovIvan) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Public API shape looks much better now, thanks! No blockers from my side, just a few nitpicks. But please wait for iOS folks' feedback before proceeding

For "Release Notes" - please describe it as a single feature, not like 3 separate ones

@svastven Vendula Švastalová (svastven) force-pushed the svastven/sizing-interop-views-in-compose branch from e4dc3b4 to 84e4f98 Compare March 2, 2026 09:12
val widthConstraint = if (fixedWidth != null) {
widthAnchor.constraintEqualToConstant(fixedWidth.value.toDouble())
} else {
widthAnchor.constraintLessThanOrEqualToConstant(maxWidth.value.toDouble())

@ASalavei Andrei Salavei (ASalavei) Mar 2, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Interesting approach!
To make the constraintLessThanOrEqualToConstant works properly, it's needed to disable two of four constraints between userComponent and its parent userComponentHostView. Otherwhise it looks like a constraint conflict: userComponent has constraints to its parent, which is fixed in size (and prevent the userComponent from shrinking), also at the same time it has active constraintLessThanOrEqualToConstant - which limits the view size, but may cause conflicts with the size of the userComponentHostView.

Also, userComponent.superview?.layoutIfNeeded() might be helpful before the measurement.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes, userComponentHostView should be used to measure size, not userComponent. Thanks for catching!

As for layoutIfNeeded() I found that not necessary since fitting size seems to calculate with the constraints that are active. I would use that only if we found cases that it is actually really needed. Wdyt?

*/
@Stable
@ExperimentalComposeUiApi
class UIKitInteropRemeasureRequester @RememberInComposition constructor() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I still wondering if we can detect requestRemeasure by analyzing the frame of the "weighted" userComponent size inside the userComponentHostView.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I am writing up a more comprehensive doc where all the cases should be explained.

@svastven Vendula Švastalová (svastven) merged commit 7815b27 into jb-main Mar 4, 2026
69 of 74 checks passed
@svastven Vendula Švastalová (svastven) deleted the svastven/sizing-interop-views-in-compose branch March 4, 2026 10:10
@Kpotko Vlad Konstantinov (Kpotko) requested review from a team and removed request for a team March 5, 2026 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants