2

Currently I'm trying to make 3 buttons in a horizontal group of 3 that have equal spacing

UIStackView * menuButtons = [[UIStackView alloc] initWithFrame:CGRectMake(0, 0, 60, 16)];
  menuButtons.axis = UILayoutConstraintAxisHorizontal;
  menuButtons.alignment = UIStackViewAlignmentBottom;
  menuButtons.spacing = 6;
  menuButtons.distribution = UIStackViewDistributionEqualSpacing;

UIButton* btnOne = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 16, 16)];
UIButton* btnTwo = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 16, 16)];
UIButton* btnThree = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 16, 16)];

  [menuButtons addArrangedSubview:btnOne];
  [menuButtons addArrangedSubview:btnTwo];
  [menuButtons addArrangedSubview:btnThree];

ive noticed when I inspect the frame of the button views after adding them to my stackview programatically, they all show different sizes than originally set, when I expect them all to still be 16

ie: btnOne CGSize(17, 16), btnTwo CGSize(23.5, 23,5), btnThree CGSize(21.3, 21.3)

I don't understand why this happens, and I've tried all the distributions but I can't figure this out when I'm not setting the frames on these views anywhere else

user286152
  • 117
  • 1
  • 2
  • 12
  • 1
    As I understand it, `UIStackView` **really** needs auto-layout to, well, *layout* its arranged views. Since you are explicitly setting the frame of the stack view, and not letting auto-layout / constraints to its job, you end up with unexpected results. – DonMag Jun 24 '17 at 19:59

1 Answers1

1

Here is an example - based on your code - using auto-layout constraints.

Note that you do NOT need to specify width and height constraints for your UIStackView, as it will expand as needed to fit the arranged subviews.

If you do set a width constraint, you'll end up with (likely) unexpected results, because you've also specified fixed-width spacing of 6.

So, you would want either:

  1. width constraint + UIStackViewDistributionEqualSpacing, or
  2. no width constraint + default distribution + .spacing = 6

Hope this helps...

//
//  StackTestViewController.m
//
//  Created by Don Mag on 6/24/17.
//

#import "StackTestViewController.h"

@interface StackTestViewController ()

@end

@implementation StackTestViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupMenuButtons];
}

- (void)setupMenuButtons {

    // instantiate a UIStackView
    UIStackView *menuButtons = [[UIStackView alloc] init];

    // horizontal
    menuButtons.axis = UILayoutConstraintAxisHorizontal;

    // spacing between arranged views
    menuButtons.spacing = 6;

    // instantiate 3 buttons
    UIButton* btnOne = [UIButton new];
    UIButton* btnTwo = [UIButton new];
    UIButton* btnThree = [UIButton new];

    // give 'em background colors so we can see them
    btnOne.backgroundColor = [UIColor redColor];
    btnTwo.backgroundColor = [UIColor greenColor];
    btnThree.backgroundColor = [UIColor blueColor];

    // for each button,
    //  tell it not to use Autoresizing Mask
    //  set width and height constraints each to 16
    for (UIButton *b in @[btnOne, btnTwo, btnThree]) {
        [b setTranslatesAutoresizingMaskIntoConstraints:NO];
        [b.widthAnchor constraintEqualToConstant:16.0].active = YES;
        [b.heightAnchor constraintEqualToConstant:16.0].active = YES;
    }

    // add them to the Stack View
    [menuButtons addArrangedSubview:btnOne];
    [menuButtons addArrangedSubview:btnTwo];
    [menuButtons addArrangedSubview:btnThree];

    // add the Stack View to self view
    [self.view addSubview:menuButtons];

    // tell Stack View not to use Autoresizing Mask
    [menuButtons setTranslatesAutoresizingMaskIntoConstraints:NO];

    // set X and Y position for the Stack View (just using 80,80 for this example)
    [menuButtons.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:80.0].active = YES;
    [menuButtons.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:80.0].active = YES;

}

#end
DonMag
  • 69,424
  • 5
  • 50
  • 86