iOS 7 iPad Orientation issue, when view moves upsi

2019-09-02 02:43发布

问题:

In my application i wan't to move/animate my ViewController's view to upward direction after appearance of keyboard over UITextField.

and this must support for all orientation.i.e:
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight.

For UIInterfaceOrientationPortrait my code is working fine as shown below:

But for UIInterfaceOrientationPortraitUpsideDown and UIInterfaceOrientationLandscapeLeft it is not working. please see below screenshots:

For UIInterfaceOrientationLandscapeLeft view moves towards right side instead of upward side.

For UIInterfaceOrientationPortraitUpsideDown view moves towards down side instead of upward side.

This is only issue in iOS 7. I have checked this in iOS 8, it is working fine.

I have used below code for animating UIView on keyboard appearance:

static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 264;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 352;

    -(void) textFieldDidBeginEditing:(UITextField *)textField
    {
        CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];

        CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];

        CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;

        CGFloat numerator = midline - viewRect.origin.y - MINIMUM_SCROLL_FRACTION * viewRect.size.height;
        CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION) * viewRect.size.height;
        CGFloat heightFraction = numerator / denominator;

        if (heightFraction < 0.0)
        {
            heightFraction = 0.0;
        }
        else if (heightFraction > 1.0)
        {
            heightFraction = 1.0;
        }

        UIInterfaceOrientation orientation =
        [[UIApplication sharedApplication] statusBarOrientation];
        if (orientation == UIInterfaceOrientationPortrait ||
            orientation == UIInterfaceOrientationPortraitUpsideDown)
        {
            animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
        }
        else
        {
            animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
        }

        if(self.view.frame.origin.y != 0.000000)
        {
            self.view.frame = CGRectMake(self.view.frame.origin.x,0.0,self.view.frame.size.width,self.view.frame.size.height);
        }

        CGRect viewFrame = self.view.frame;
        viewFrame.origin.y -= animatedDistance;

        NSLog(@"View frame y pos did start: %f ",animatedDistance);

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

        [self.view setFrame:viewFrame];

        [UIView commitAnimations];
    }

    -(void) textFieldDidEndEditing:(UITextField *)textField
    {
        CGRect viewFrame = self.view.frame;
        viewFrame.origin.y += animatedDistance;

        NSLog(@"View frame y pos did end: %f ",animatedDistance);

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

        [self.view setFrame:viewFrame];

        [UIView commitAnimations];
    }

Thanks

回答1:

Gulp. Can I make some suggestions ?

First, I would attach an event to UIKeyboardWillShowNotification and UIKeyboardWillHideNotification rather than using the textFieldDidBeginEditing event.

Supposing I ran your app on my iPad, but had a Bluetooth keyboard connected. I would tap in the text box, your UIView would shift up, but the iPad wouldn't display an onscreen keyboard as it knows I wouldn't need it.

The other advantage is that you're currently using hardcoded heights for the onscreen keyboard. Ooooh, this isn't a good idea.

Have a look at my screenshot in this posting to give one (just one!) example of why this isn't a good idea:

iPad keyboard height

If you choose to go down the UIKeyboardWillShowNotification route, you can measure the correct height of the keyboard...

-(void)onKeyboardWillShow:(NSNotification*)notification
{
    //  The user has turned on the onscreen keyboard.
    //
    NSDictionary *info = [notification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    CGRect keyboardFrame = [kbFrame CGRectValue];
    keyboardFrame = [self.view convertRect:keyboardFrame fromView:nil];

    CGFloat keyboardHeight = keyboardFrame.size.height;
}

Here's a sample XCode project I've knocked up, which demonstrates how to resize a control, to make it (almost) fill the entire screen, and resize it when the device's orientation & onscreen keyboard visibility changes:

OnScreenKeyboardTest XCode 6.1 project

You'll see that it has a "Dismiss" button, which makes the onscreen keyboard go away. This code (should) run on all iPhones & iPads.

Phew ! Hope this helps.