Skip to content

Commit ecf2228

Browse files
committed
Use autolayout constraints to set size of custom bar button item
This fixes an issue where the frame for the custom view can be set to the incorrect y-offset upon setting the custom frame. In iOS 11, this behavior changed, as UIBarButtonItem went from being using springs-and-struts for sizing, to using a UIStackView, and thus using Autolayout. This lead to the superview of having a frame of (0, 22, 0, 0) at the first layout pass. By moving to using NSLayoutConstaints, we can now properly size our custom view. See also: https://gist.github.com/niw/569b49648fcab22124e1d12c195fe595 See also: https://stackoverflow.com/questions/10988918/change-width-of-a-uibarbuttonitem-in-a-uinavigationbar
1 parent 8ba9796 commit ecf2228

File tree

1 file changed

+29
-15
lines changed

1 file changed

+29
-15
lines changed

lib/ios/RNNUIBarButtonItem.m

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
#import "RNNUIBarButtonItem.h"
44
#import "RCTConvert+UIBarButtonSystemItem.h"
55

6+
@interface RNNUIBarButtonItem ()
7+
8+
@property (nonatomic, strong) NSLayoutConstraint *widthConstraint;
9+
@property (nonatomic, strong) NSLayoutConstraint *heightConstraint;
10+
11+
@end
12+
613
@implementation RNNUIBarButtonItem
714

815
-(instancetype)init:(NSString*)buttonId withIcon:(UIImage*)iconImage {
9-
UIButton* button = [[UIButton alloc] init];
10-
[button addTarget:self action:@selector(onButtonPressed) forControlEvents:UIControlEventTouchUpInside];
11-
[button setImage:iconImage forState:UIControlStateNormal];
12-
self = [super initWithCustomView:button];
16+
self = [super initWithImage:iconImage style:UIBarButtonItemStylePlain target:nil action:nil];
1317
self.buttonId = buttonId;
1418
return self;
1519
}
@@ -26,27 +30,37 @@ -(instancetype)init:(NSString*)buttonId withCustomView:(RCTRootView *)reactView
2630
reactView.sizeFlexibility = RCTRootViewSizeFlexibilityWidthAndHeight;
2731
reactView.delegate = self;
2832
reactView.backgroundColor = [UIColor clearColor];
33+
self.widthConstraint = [NSLayoutConstraint constraintWithItem:reactView
34+
attribute:NSLayoutAttributeWidth
35+
relatedBy:NSLayoutRelationEqual
36+
toItem:nil
37+
attribute:NSLayoutAttributeNotAnAttribute
38+
multiplier:1.0
39+
constant:1.0];
40+
self.heightConstraint = [NSLayoutConstraint constraintWithItem:reactView
41+
attribute:NSLayoutAttributeHeight
42+
relatedBy:NSLayoutRelationEqual
43+
toItem:nil
44+
attribute:NSLayoutAttributeNotAnAttribute
45+
multiplier:1.0
46+
constant:1.0];
47+
[NSLayoutConstraint activateConstraints:@[self.widthConstraint, self.heightConstraint]];
2948
self.buttonId = buttonId;
3049
return self;
3150
}
32-
33-
-(instancetype)init:(NSString*)buttonId withSystemItem:(NSString *)systemItemName {
51+
52+
- (instancetype)init:(NSString*)buttonId withSystemItem:(NSString *)systemItemName {
3453
UIBarButtonSystemItem systemItem = [RCTConvert UIBarButtonSystemItem:systemItemName];
3554
self = [super initWithBarButtonSystemItem:systemItem target:nil action:nil];
3655
self.buttonId = buttonId;
3756
return self;
3857
}
3958

4059
- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {
41-
CGSize size = rootView.intrinsicContentSize;
42-
rootView.frame = CGRectMake(0, 0, size.width, size.height);
43-
self.width = size.width;
44-
}
45-
46-
- (void)onButtonPressed {
47-
[self.target performSelector:self.action
48-
withObject:self
49-
afterDelay:0];
60+
self.widthConstraint.constant = rootView.intrinsicContentSize.width;
61+
self.heightConstraint.constant = rootView.intrinsicContentSize.height;
62+
[rootView setNeedsUpdateConstraints];
63+
[rootView updateConstraintsIfNeeded];
5064
}
5165

5266
@end

0 commit comments

Comments
 (0)