-
-
Notifications
You must be signed in to change notification settings - Fork 598
fix(iOS 26, Stack): center view inside bar button item #3449
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
base: @kligarski/fix-header-pressable-hit-slop-fabric
Are you sure you want to change the base?
fix(iOS 26, Stack): center view inside bar button item #3449
Conversation
f8af1a1 to
a61fbc5
Compare
a61fbc5 to
cad5e26
Compare
| NSLayoutConstraint *heightEqual = [wrapperView.heightAnchor constraintEqualToAnchor:self.heightAnchor]; | ||
| heightEqual.priority = UILayoutPriorityDefaultHigh; | ||
| heightEqual.active = YES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, we can remove height constraints and allow wrapperView to grow in height. This would make the entire liquid glass button interactive (currently, area inside liquid glass button but above and below custom view is not interactive as wrapperView is stretched by UIKit only in horizontal axis).
| _layoutMetrics = layoutMetrics; | ||
| [self invalidateIntrinsicContentSize]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: we may consider calling it only if layoutMetrics have changed
Description
Fixes alignment of custom view inside bar button item on iOS 26.
Note
Please note that this will also change positioning of bar button items with
hidesSharedBackground: trueon iOS 26.before3449.mov
after3449.mov
Closes #2990.
Explanation
Starting from iOS 26, custom view inside
UIBarButtonItemis stretched to at least 36 width. This causes ourRNSScreenStackHeaderSubviewto stretch if its width is smaller than 36, leaving subviews in the same origin (for one subview, it's usually(0,0); that's why it is aligned to the left, visible in "before" recording).In order to mitigate this, we add
wrapperViewwhich will be stretched by UIKit to required minimum size.RNSScreenStackHeaderSubviewwill be centered inside of it. Additional constraints and properties needed to be added to make sure thatwrapperViewis not stretched to all available space inUINavigationBar(this would happen inheaderRightif we used onlywrapperView.width >= RNSScreenStackHeaderSubview.widthconstraint):wrapperView.width == RNSScreenStackHeaderSubview.width- makes sure that wrapper matches content. By using lower priority than default, we allow UIKit to "take over" with its minimum width, while maintaining "fit-content"/"content hugging" behavior,[self setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]- prevents stretching to all available width inUINavigationBar.RNSScreenStackHeaderSubviewneeds to useintrinsicContentSizein order to bridge auto-layout centering and frame size from Yoga.Changes
UIBarButtonItemandRNSScreenStackHeaderSubviewRNSScreenStackHeaderSubviewinsidewrapperViewwhile maintaining correct sizing via auto layoutintrinsicContentSizeto bridge between auto-layout and frames calculated by YogaRNSScreenStackHeaderSubviewcan have non-zero offset (which was not the case previously); without change toself.bounds, this offset would be accounted for 2 times when using[self convertRect:frame toView:ancestorView])Test code and steps to reproduce
Run
Test3446.Checklist