iosautolayoutuiinterfaceorientation

Date pickers selection's overlay not adjusting when screen rotates


I've got a view with two date pickers set to cover the entire view's height and half a width each, so that they are filling the entire view.

I've then added an overlay to each picker to make the selection more visible, like this:

-(void)drawOverlays {
    if (_overlay1 != nil) {
        [_overlay1 removeFromSuperview];
    }
    if (_overlay2 != nil) {
        [_overlay2 removeFromSuperview];
    }
    _overlay1 = [[UIView alloc] initWithFrame:CGRectMake(_startPicker.bounds.origin.x, (_startPicker.frame.size.height/2)-19, _startPicker.bounds.size.width, 38)];
    _overlay1.backgroundColor = [UIColor redColor];
    _overlay1.alpha = 0.5f;
    [_startPicker addSubview:_overlay1];
    _overlay2 = [[UIView alloc] initWithFrame:CGRectMake(_endPicker.bounds.origin.x, (_endPicker.frame.size.height/2)-19, _endPicker.bounds.size.width, 38)];
    _overlay2.backgroundColor = [UIColor redColor];
    _overlay2.alpha = 0.5f;
    [_endPicker addSubview:_overlay2];
}

I'm calling this method from the -viewDidLayoutSubviews method and from the -viewWillTransitionToSize:withTransitionCoordinator method, and the first time the view appears everything is fine.

Then I rotate my iPad and the overlays are shown inverted, meaning that when in landscape the overlays are the size I want for the portrait and vice versa.

What's wrong with my code?


Solution

  • You will be much better off using constraints and letting auto-layout handle the resizing:

    -(void)drawOverlays {
    
        if (_overlay1 != nil) {
            [_overlay1 removeFromSuperview];
        }
        if (_overlay2 != nil) {
            [_overlay2 removeFromSuperview];
        }
    
        //_overlay1 = [[UIView alloc] initWithFrame:CGRectMake(_startPicker.bounds.origin.x, (_startPicker.frame.size.height/2)-19, _startPicker.bounds.size.width, 38)];
    
        // instantiate overlay1
        _overlay1 = [UIView new];
        _overlay1.backgroundColor = [UIColor redColor];
        _overlay1.alpha = 0.5f;
    
        // add as subview of startPicker
        [_startPicker addSubview:_overlay1];
    
        //_overlay2 = [[UIView alloc] initWithFrame:CGRectMake(_endPicker.bounds.origin.x, (_endPicker.frame.size.height/2)-19, _endPicker.bounds.size.width, 38)];
    
        // instantiate overlay2
        _overlay2 = [UIView new];
        _overlay2.backgroundColor = [UIColor redColor];
        _overlay2.alpha = 0.5f;
    
        // add as subview of endPicker
        [_endPicker addSubview:_overlay2];
    
        // we want to use auto-layout / constraints
        _overlay1.translatesAutoresizingMaskIntoConstraints = NO;
        _overlay2.translatesAutoresizingMaskIntoConstraints = NO;
    
        [NSLayoutConstraint activateConstraints:@[
    
            // constrain overlay1 to startPicker
            //  centerY
            //  leading / trailing = 0
            //  height = 38
            [_overlay1.centerYAnchor constraintEqualToAnchor:_startPicker.centerYAnchor],
            [_overlay1.leadingAnchor constraintEqualToAnchor:_startPicker.leadingAnchor constant:0.0],
            [_overlay1.trailingAnchor constraintEqualToAnchor:_startPicker.trailingAnchor constant:0.0],
            [_overlay1.heightAnchor constraintEqualToConstant:38.0],
    
            // constrain overlay2 to startPicker
            //  centerY
            //  leading / trailing = 0
            //  height = 38
            [_overlay2.centerYAnchor constraintEqualToAnchor:_endPicker.centerYAnchor],
            [_overlay2.leadingAnchor constraintEqualToAnchor:_endPicker.leadingAnchor constant:0.0],
            [_overlay2.trailingAnchor constraintEqualToAnchor:_endPicker.trailingAnchor constant:0.0],
            [_overlay2.heightAnchor constraintEqualToConstant:38.0],
    
            ]
    
         ];
    
    }
    

    And, this only needs to be called from viewDidLoad (or wherever else you may find it appropriate). There is no need for it to be -- and in fact, it should not be -- called from viewDidLayoutSubviews or viewWillTransitionToSize.

    As a side note -- if you are using remove and re-add to show and hide them, you'll also get a little better optimization if you add them once, and then set the .hidden property to YES or NO.