0

I just struggled quite a while with this, so will document it for others.

Here's the problem I was having. With an iPad app, supporting iOS7, I have a modal view controller that has a text field near the bottom the modal. Thus, when the keyboard appears, I wanted to move that modal up so the text field would still be visible with the keyboard present. With iOS8, this problem has a pretty clean solution (e.g., see Moving a modally presented UIViewController up when keyboard appears on iPad with iOS8). With iOS7 I was using self.myNavController.view.superview.center for repositioning, but ran into problems when trying to move the modal given the appearance of the keyboard. The coordinate CGPoint adjustments I was using would not move the modal in the right direction with all four rotations/orientations of the iPad.

The problem in part lies in how iOS7 does the rotation-- with transforms. However, I was unable to resolve the issue using CGPointApplyAffineTransform, or conversion of points using views (e.g., convertPoint:fromView:).

Community
  • 1
  • 1
Chris Prince
  • 7,288
  • 2
  • 48
  • 66

1 Answers1

0

The solution I found to this problem involved a few steps:

1) I found it necessary to change the center of the modal (an assignment to self.myNavController.view.superview.center) relative to the center of the screen. I computed the center of the screen based on [UIScreen mainScreen].bounds.size. For some example code, I used the method screenCenter below.

// Adapted from: http://stackoverflow.com/questions/24150359/is-uiscreen-mainscreen-bounds-size-becoming-orientation-dependent-in-ios8
+ (CGSize) screenSize;
{
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    CGSize rotatedSize;

    if ([UIDevice ios7OrEarlier] && [[SMRotation session] isLandscape]) {
        rotatedSize = CGSizeMake(screenSize.height, screenSize.width);
    }
    else {
        rotatedSize = screenSize;
    }

    return rotatedSize;
}

+ (CGPoint) screenCenter;
{
    CGSize size = [self screenSize];
    CGPoint center = CGPointMake(size.width/2.0, size.height/2);
    return center;
}

2) Now, given that you have computed the amount that you have to shift the modal upwards (e.g., given the keyboard height and your modal height and the position of the text field on the modal), call this amount dy. I next found it necessary if the app was in an inverted rotation (upside down portrait or landscape), to change the sign of dy before applying it to the CGPoint center position I was calculating. Something like this:

CGPoint newCenter = [SMRotation screenCenter];
if ([SMRotation session].isInverted) {
    dy = -dy;
}
newCenter.y += dy;

With some of the code for isInverted here:

- (BOOL) isInverted;
{
    switch (self.interfaceOrientation) {
        case UIInterfaceOrientationPortraitUpsideDown:
        case UIInterfaceOrientationLandscapeRight:
            return YES;

        case UIInterfaceOrientationPortrait:
        case UIInterfaceOrientationLandscapeLeft:
        case UIInterfaceOrientationUnknown:
            return NO;
    }
}

3) Then, if the app was in landscape I found it necessary to swap the x and y coordinates. Something like this:

    if ([SMRotation session].isLandscape) {
        newCenter = CGPointMake(newCenter.y, newCenter.x);
    }

4 Finally, I did the assignment to update the center of the modal:

self.myNavController.view.superview.center = newCenter;
Chris Prince
  • 7,288
  • 2
  • 48
  • 66