I have a subclass of UIView that will be a tooltip that can be displayed at the bottom of any view controller to display a tooltip / error message / success message / etc. There are two UILabel in the UILabel : a UILabel on the left side and a UIView on the right side, it can be anything (but often used as a UIButton ).
TooltipView.h
@interface TooltipView : UIView @property (nonatomic, readonly) UILabel *textLabel; @property (nonatomic) UIView *rightView;
TooltipView.m
static CGFloat const kSubviewToSuperviewSpacing = 7.0f; static CGFloat const kTextLabelToRightViewHorizontalSpacing = 7.0f; @implementation TooltipView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { _textLabel = [[UILabel alloc] init]; _textLabel.numberOfLines = 0; [_textLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; [self addSubview:_textLabel]; } return self; } - (void)setRightView:(UIView *)rightView { if (_rightView != rightView) { _rightView = rightView; [self addSubview:_rightView]; [self setNeedsDisplay]; } } - (BOOL)translatesAutoresizingMaskIntoConstraints { return NO; } - (void)updateConstraints { self.didUpdateConstraints = YES; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.textLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0f constant:kSubviewToSuperviewSpacing]]; NSMutableDictionary *metricsDictionary = [@{@"subviewToSuperviewSpacing": @(kSubviewToSuperviewSpacing)} mutableCopy]; NSMutableDictionary *viewsDictionary = [@{@"textLabel": self.textLabel} mutableCopy]; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-subviewToSuperviewSpacing-[textLabel]-subviewToSuperviewSpacing-|" options:0 metrics:metricsDictionary views:viewsDictionary]]; if (self.rightView) { metricsDictionary[@"textLabelToRightViewHorizontalSpacing"] = @(kTextLabelToRightViewHorizontalSpacing); viewsDictionary[@"rightView"] = self.rightView; [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-subviewToSuperviewSpacing-[rightView]-subviewToSuperviewSpacing-|" options:0 metrics:metricsDictionary views:viewsDictionary]]; [self addConstraint:[NSLayoutConstraint constraintWithItem:self.rightView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:kSubviewToSuperviewSpacing]]; } [super updateConstraints]; }
I also have a view controller to test this with UILabel as a rightView . It subclasses the UIViewController , and its only method overrides loadView :
- (void)loadView { TooltipView *tooltipView = [[TooltipView alloc] initWithFrame:CGRectZero]; tooltipView.textLabel.text = @"Test 1"; UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectZero]; testLabel.text = @"Hello there"; [testLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; tooltipView.rightView = testLabel; self.view = tooltipView;
}
Finally, in the view controller, where I want to display the tooltip, I add TooltipViewController as the child view controller. In the end, this will be triggered by some event, but for testing purposes, I have this addition to viewWillAppear:
- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; self.aViewController = [[TooltipViewController alloc] init]; self.aViewController.view.backgroundColor = [UIColor whiteColor]; [self addChildViewController:self.aViewController]; [self.view addSubview:self.aViewController.view]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:@{@"view": self.aViewController.view}]]; [self.aViewController.view addConstraint:[NSLayoutConstraint constraintWithItem:self.aViewController.view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:150.0f]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.aViewController.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]]; [self.aViewController didMoveToParentViewController:self]; }
However, at runtime, the textLabel and rightView appear correct, but the tooltipView frame tooltipView set to CGRectZero , and none of the three views appears on the screen.
Thanks in advance!
EDIT
I even tried to completely remove the textLabel and rightView , so it's just a UIView with restrictions on the leading, final, lower and upper levels. Nothing is ambiguous, but the presentation frame is still CGRectZero .
ios objective-c autolayout uiviewcontroller uiview
sethfri
source share