Skip to content

Commit 72412dc

Browse files
fix(ios): center RNNReactButtonView inside navigation bar platter (#8300)
* fix(ios): add Auto Layout constraints to RNNReactButtonView on iOS 26 On iOS 26 the Liquid Glass navigation bar wraps custom-view bar button items in several internal layout containers. Without explicit size constraints the wrapper views can collapse to zero height after a pop → tab-switch → tab-switch → push cycle, making the React button invisible. - Guard all new logic behind @available(iOS 26.0, *) AND a runtime check for UIDesignRequiresCompatibility (compatibility mode disables Liquid Glass and uses the legacy view hierarchy) - Set translatesAutoresizingMaskIntoConstraints = NO - Add width/height constraints at UILayoutPriorityDefaultHigh - Update constraints in didMountComponentsWithRootTag: after sizeToFit Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ios): center RNNReactButtonView inside navigation bar platter On iOS 26 the internal _UITAMICAdaptorView wrapper is wider than the React button content and UIKit pins the custom view to the leading edge. Apply a one-time horizontal CGAffineTransform in layoutSubviews to center the view. Guarded by @available(iOS 26.0, *) and UIDesignRequiresCompatibility check. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent e4e5049 commit 72412dc

1 file changed

Lines changed: 59 additions & 2 deletions

File tree

ios/RNNReactButtonView.mm

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#import "RNNReactButtonView.h"
2+
#import <React/RCTSurface.h>
23

3-
@implementation RNNReactButtonView
4+
@implementation RNNReactButtonView {
5+
NSLayoutConstraint *_widthConstraint;
6+
NSLayoutConstraint *_heightConstraint;
7+
BOOL _didCenter;
8+
}
49

510
- (instancetype)initWithHost:(RCTHost *)host
611
moduleName:(NSString *)moduleName
@@ -10,15 +15,67 @@ - (instancetype)initWithHost:(RCTHost *)host
1015
reactViewReadyBlock:(RNNReactViewReadyCompletionBlock)reactViewReadyBlock {
1116
self = [super initWithHost:host moduleName:moduleName initialProperties:initialProperties eventEmitter:eventEmitter sizeMeasureMode:convertToSurfaceSizeMeasureMode(RCTRootViewSizeFlexibilityWidthAndHeight) reactViewReadyBlock:reactViewReadyBlock];
1217
[host.surfacePresenter addObserver:self];
13-
self.backgroundColor = UIColor.clearColor;
18+
self.backgroundColor = [UIColor clearColor];
19+
20+
if (@available(iOS 26.0, *)) {
21+
if (![self designRequiresCompatibility]) {
22+
self.translatesAutoresizingMaskIntoConstraints = NO;
23+
_widthConstraint = [self.widthAnchor constraintEqualToConstant:0];
24+
_heightConstraint = [self.heightAnchor constraintEqualToConstant:0];
25+
_widthConstraint.priority = UILayoutPriorityDefaultHigh;
26+
_heightConstraint.priority = UILayoutPriorityDefaultHigh;
27+
_widthConstraint.active = YES;
28+
_heightConstraint.active = YES;
29+
_didCenter = NO;
30+
}
31+
}
1432

1533
return self;
1634
}
1735

36+
- (BOOL)designRequiresCompatibility {
37+
static BOOL checked = NO;
38+
static BOOL result = NO;
39+
if (!checked) {
40+
checked = YES;
41+
result = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIDesignRequiresCompatibility"] boolValue];
42+
}
43+
return result;
44+
}
45+
1846
- (void)didMountComponentsWithRootTag:(NSInteger)rootTag {
1947
if (self.surface.rootTag == rootTag) {
2048
[super didMountComponentsWithRootTag:rootTag];
2149
[self sizeToFit];
50+
if (@available(iOS 26.0, *)) {
51+
if (![self designRequiresCompatibility]) {
52+
[self updateConstraintsToFitSize];
53+
}
54+
}
55+
}
56+
}
57+
58+
- (void)updateConstraintsToFitSize {
59+
CGSize size = self.frame.size;
60+
if (size.width > 0 && size.height > 0) {
61+
_widthConstraint.constant = size.width;
62+
_heightConstraint.constant = size.height;
63+
}
64+
}
65+
66+
- (void)layoutSubviews {
67+
[super layoutSubviews];
68+
if (@available(iOS 26.0, *)) {
69+
if ([self designRequiresCompatibility]) return;
70+
if (!_didCenter && self.superview && self.frame.size.width > 0) {
71+
CGFloat wrapperWidth = self.superview.bounds.size.width;
72+
CGFloat selfWidth = self.frame.size.width;
73+
if (wrapperWidth > selfWidth) {
74+
_didCenter = YES;
75+
CGFloat tx = (wrapperWidth - selfWidth) / 2.0;
76+
self.layer.affineTransform = CGAffineTransformMakeTranslation(tx, 0);
77+
}
78+
}
2279
}
2380
}
2481

0 commit comments

Comments
 (0)