UIButton stops working when using auto layout

I put together a simple view controller programmatically using two buttons on it. If I go to an old school and set the size of the frame for the layout, then everything will be fine. However, if I use layout restrictions for the layout, the buttons are displayed fine, but they do not respond to clicks. They don’t even give out. My loadview method is given below in a form that does not allow buttons to work. If the frame setting code is uncommented, and the addition of restrictions is added, then the buttons begin to respond to clicks as expected. Does anyone know what is going on? I would like to translate all the old hard code in my code base to be based on restrictions, but it seems to fall on the first hurdle.

- (void)loadView { self.view = [UIView new]; self.view.translatesAutoresizingMaskIntoConstraints = NO; self.navigationItem.title = @"Landing Page"; UIButton *buildExercisesButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.buildExercisesButton = buildExercisesButton; // buildExercisesButton.frame = CGRectMake(20, 312, 164, 44); self.buildExercisesButton.translatesAutoresizingMaskIntoConstraints = NO; [self.buildExercisesButton setTitle:@"Build Exercises" forState:UIControlStateNormal]; [self.buildExercisesButton addTarget:self action:@selector(buildExercisesButtonPressed) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.buildExercisesButton]; UIButton *organiseExercisesButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.organiseExercisesButton = organiseExercisesButton; // organiseExercisesButton.frame = CGRectMake(192, 312, 164, 44); self.organiseExercisesButton.translatesAutoresizingMaskIntoConstraints = NO; [self.organiseExercisesButton setTitle:@"Organise Exercises" forState:UIControlStateNormal]; [self.organiseExercisesButton addTarget:self action:@selector(organiseExercisesButtonPressed) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.organiseExercisesButton]; NSDictionary *variables = NSDictionaryOfVariableBindings(buildExercisesButton, organiseExercisesButton); NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-[buildExercisesButton(organiseExercisesButton)]-[organiseExercisesButton]-|" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:nil views:variables]; [self.view addConstraints:constraints]; constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[buildExercisesButton]-|" options:0 metrics:nil views:variables]; [self.view addConstraints:constraints]; } 

In viewDidAppear, I print the button frames. They give strange values ​​that I don’t know if this is connected or not. Buttons are actually displayed next to each other in the center of the screen.

 buildExercisesButton: {{20, -63}, {164, 44}} organiseExercisesButton: {{192, -63}, {164, 44}} 
+6
source share
5 answers

It seems that the problem was second:

 self.view.translatesAutoresizingMaskIntoConstraints = NO; 

On this line, the view was not full-screen, starting from the upper left corner, as expected, but started somewhere near the center. Therefore, although the buttons were near the center of the screen, they were actually outside the containing view. When I deleted this line, everything started working.

I assume I found gotcha for translatesAutoresizingMaskIntoConstraints . Although you should disable it in order to use constraints, that is, only on exact representations that use constraints, and not for the containing view, unless it uses constraints. In this case, I turned off translatesAutoresizingMaskIntoConstraints on the containing view, but should not have, because it had no restrictions for it.

+1
source

You need to define constraints for the view you are adding, or set the translatesAutoresizingMaskIntoConstraints property to YES .

+2
source

It appears that the UIButton frames UIButton off screen. Touch events depend on the occurrence of button images not in them, so they do not respond.

Why are you using auto-layout instead of setting frames?

+1
source

I ran into the same problem. In my case:

 self.view \- ... \_self.wrapper \_self.button 

The code does not work:

 NSDictionary *metrics = @{@"padding":[NSNumber numberWithFloat:kGridPadding]}; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[head]-padding-[wrapper]-|" options:0 metrics:metrics views:views]]; 

The reason is that the height of the "wrapper" is 0, although the button is still visible. Therefore, it can be fixed by setting enough width and height as follows:

 NSDictionary *metrics = @{@"padding":[NSNumber numberWithFloat:kGridPadding], @"screenHeight":[NSNumber numberWithFloat:self.view.bounds.size.height]}; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[head]-padding-[wrapper(screenHeight)]-|" options:0 metrics:metrics views:views]]; 

-> the best way is to increase the size of the wrapper automatically, but I don’t know how to do it now?

+1
source

If you are performing a pure storyboard for auto-detection, try increasing the Vertical Crawl Priority and the Vertical Compression Priority:

enter image description here

+1
source

Source: https://habr.com/ru/post/953724/


All Articles