Search code examples
iosnslayoutconstraint

How to correctly move a UIView below UIButtons in a row


I'm making a kind of tab bar with an indicator below of which tab is selected. My view hierarchy is very simple:

---------------------------------
|-------------     -------------|
||            |    |           ||
||  Button 1  |    |  Button 2 ||
||____________|    |___________||
| ------------                  |
---------------------------------

I'm setting the indicator leading and trailing constraints to be the same as button 1 initially:

self.indicatorLeadingConstraint = [self.indicatorView.leadingAnchor constraintEqualToAnchor:self.firstButton.leadingAnchor];
self.indicatorLeadingConstraint.active = YES;
self.indicatorTrailingConstraint = [self.indicatorView.trailingAnchor constraintEqualToAnchor:self.firstButton.trailingAnchor];
self.indicatorTrailingConstraint.active = YES;

I then update them when a button is tapped:

self.indicatorLeadingConstraint.active = NO;
self.indicatorLeadingConstraint = [self.indicatorView.leadingAnchor constraintEqualToAnchor:button.leadingAnchor];
self.indicatorLeadingConstraint.active = YES;

self.indicatorTrailingConstraint.active = NO;
self.indicatorTrailingConstraint = [self.indicatorView.trailingAnchor constraintEqualToAnchor:button.trailingAnchor];
self.indicatorTrailingConstraint.active = YES;

This actually works fine, however I get a warning in the console:

(
"<NSLayoutConstraint:0x600001332620 H:[UIButton:0x7ffa68556530'First (0)']-(16)-[UIButton:0x7ffa6865e0f0'Second (0)']   (active)>",
"<NSLayoutConstraint:0x600001318a00 IndicatorView.leading == UIButton:0x7ffa6865e0f0'Second (0)'.leading   (active, names: IndicatorView:0x7ffa6865eb20 )>",
"<NSLayoutConstraint:0x600001332760 IndicatorView.trailing == UIButton:0x7ffa68556530'First (0)'.trailing   (active, names: IndicatorView:0x7ffa6865eb20 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600001332620 H:[UIButton:0x7ffa68556530'First (0)']-(16)-[UIButton:0x7ffa6865e0f0'Second (0)']   (active)>

I really don't understand why moving the view in this way should have any impact on the horizontal spacing constraint between my two buttons.

EDIT Here's the final product:

enter image description here


Solution

  • Rearrange the code something like the below. I think it will solve the issue. Let me know once you have tried.

    IndicatorLeadingConstraint.isActive = false
    IndicatorTrailingContraint.isActive = false
    IndicatorLeadingConstraint = indicatorView.leadingAnchor.constraint(equalTo: sender.leadingAnchor)
    IndicatorTrailingContraint = indicatorView.trailingAnchor.constraint(equalTo: sender.trailingAnchor)
    IndicatorTrailingContraint.isActive = true
    IndicatorLeadingConstraint.isActive = true