Richard McCluskey
Richard McCluskey

Reputation: 588

iOS 8 - Changing UIScrollView's frame with AutoLayout enabled

I was updating my app for iOS 8 and adding AutoLayout constraints to all my views. They are mostly working but UIScrollView (slideUpScrollView) is giving me some trouble. There is one UIButton (toggleDrawerButton) inside it to toggle the SV's frame. In IB, there are constraints to keep the SV at the bottom with a height of 50pts. When toggleButton is pressed, it is supposed to change the SV's origin to the top of the view, simulating a drawer effect.

There is a problem with the open/close effect. When I press the toggleDrawerButton, it'll sometimes produce the effect I want just like in iOS 7 (does not call viewDidLayoutSubviews). Other times the SV will have an odd effect where viewDidLayoutSubviews is called after my frame movement. VDLS will then attempt to re-constrain the SV and toggleDrawerButton back to it's original closed position. This causes the view to be placed back at the bottom when the drawer should be opened. VDLS seems to be called randomly on toggleDrawerButton press. Sometimes it'll be called, other times it won't.

How can I correctly reposition the SV's frame to move towards the top without auto layout re-constraining it? Also, why is VDLS only called sometimes upon toggleDrawerButton press? The behavior isn't consistent which is making it harder to find a solution.

Here is the toggleDrawerButton's action code:

- (void) toggleAddEditDrawer {
if (self.drawerToggle == 0) { // Open the Drawer
    self.drawerToggle = 1;

    self.itemNameTextField.text = nil;
    self.quantityTextField.text = nil;

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.4];
    [UIView setAnimationDelay:0.0];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

    //Rotate the button and make the SV frame slide up

    self.toggleDrawerButton.transform = CGAffineTransformMakeRotation(M_PI/4);
    self.slideUpScrollView.frame = CGRectMake(0, self.tableView.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
    self.slideUpScrollView.contentSize = self.slideUpScrollView.frame.size;


    [UIView commitAnimations];
    [self.itemNameTextField becomeFirstResponder];

    NSLog(@"OPEN Toggle - tableview location is: %@",NSStringFromCGRect(self.tableView.frame));
    NSLog(@"OPEN Toggle - scrollview location is: %@",NSStringFromCGRect(self.slideUpScrollView.frame));
    NSLog(@"OPEN Toggle - toggleButton location is: %@",NSStringFromCGRect(self.toggleDrawerButton.frame));


} else { //Close the Drawer
    self.drawerToggle = 0;
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.4];
    [UIView setAnimationDelay:0.0];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

    //Reverse the rotation and  make the SV frame slide down
    self.toggleDrawerButton.transform = CGAffineTransformMakeRotation(0);
    self.slideUpScrollView.frame = CGRectMake(0, self.tableView.frame.origin.y + self.tableView.frame.size.height, self.view.frame.size.width, 50);
    self.slideUpScrollView.contentSize = self.slideUpScrollView.frame.size;

    [UIView commitAnimations];
    [self.view endEditing:YES];

    NSLog(@"CLOSE Toggle - tableview location is: %@",NSStringFromCGRect(self.tableView.frame));
    NSLog(@"CLOSE Toggle - scrollview location is: %@",NSStringFromCGRect(self.slideUpScrollView.frame));
    NSLog(@"CLOSE Toggle - toggleButton location is: %@",NSStringFromCGRect(self.toggleDrawerButton.frame));


}
NSLog(@"Drawer Posistion is: %d",self.drawerToggle);

}

Edit: Here are some console logs.

Working frame animation log:
OPEN Toggle - tableview location is: {{0, 2}, {320, 452}}
OPEN Toggle - scrollview location is: {{0, 2}, {320, 504}}
OPEN Toggle - toggleButton location is: {{128.88730162779191, -6.1126983722080901}, {62.225396744416173, 62.225396744416173}}
Drawer Posistion is: 1

VDLS frame re-constraint log:
OPEN Toggle - tableview location is: {{0, 2}, {320, 452}}
OPEN Toggle - scrollview location is: {{0, 2}, {320, 504}}
OPEN Toggle - toggleButton location is: {{128.88730162779191, -6.1126983722080901}, {62.225396744416173, 62.225396744416173}}
Drawer Posistion is: 1
VDLS - tableview location is: {{0, 2}, {320, 452}}
VDLS - scrollview location is: {{0, 454}, {320, 50}}
VDLS - toggleButton location is: {{128.88730162779191, -6.1126983722080901}, {62.225396744416173, 62.225396744416173}}

Upvotes: 0

Views: 1112

Answers (1)

Austen Chongpison
Austen Chongpison

Reputation: 3974

In general when using AutoLayout you can't manipulate a view's frame manually. You need to animate the constraint change not the frame change.

Here is info on animating a constraint: https://happyteamlabs.com/blog/ios-how-to-animate-autolayout-constraints/

And more info on setting frames when AutoLayout is enabled: Can I use setFrame and autolayout on the same view?

Upvotes: 2

Related Questions