UIKeyboardBoundsUserInfoKey is deprecated, what to use instead?

前端 未结 9 1754
我在风中等你
我在风中等你 2020-12-02 04:56

I\'m working on an iPad app using 3.2 sdk. I\'m dealing with obtaining the keyboard size to prevent my textfields from hidding behind it.

I\'m getting a Warning in

相关标签:
9条回答
  • 2020-12-02 05:42

    You simply use this code:

    //NSVale *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
    //instead of Upper line we can use either next line or nextest line.
    //NSValue *aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    NSValue *aValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
    
    0 讨论(0)
  • 2020-12-02 05:46

    I played with the previously offered solution but still had issues. Here's what I came up with instead:

        - (void)keyboardWillShow:(NSNotification *)aNotification {
        [self moveTextViewForKeyboard:aNotification up:YES];
    }
    
        - (void)keyboardWillHide:(NSNotification *)aNotification {
            [self moveTextViewForKeyboard:aNotification up:NO]; 
        }
    
    - (void) moveTextViewForKeyboard:(NSNotification*)aNotification up: (BOOL) up{
    NSDictionary* userInfo = [aNotification userInfo];
    
    // Get animation info from userInfo
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;
    
    CGRect keyboardEndFrame;
    
    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
    [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
    
    
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
    
    
    // Animate up or down
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:animationDuration];
    [UIView setAnimationCurve:animationCurve];
    
    CGRect newFrame = textView.frame;
    CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
    
    newFrame.origin.y -= keyboardFrame.size.height * (up? 1 : -1);
    textView.frame = newFrame;
    
    [UIView commitAnimations];
    }
    
    0 讨论(0)
  • 2020-12-02 05:46

    The following code fixes an issue in Jay's answer, which assumes that UIKeyboardWillShowNotification will not fire again when the keyboard is already present.

    When typing with the Japanese/Chinese keyboard, iOS fires an extra UIKeyboardWillShowNotification with the new keyboard frame even though the keyboard is already present, leading to the height of the self.textView being reduced a second time in the original code.

    This reduces self.textView to almost nothing. It then becomes impossible to recover from this problem since we will only expect a single UIKeyboardWillHideNotification the next time the keyboard is dismissed.

    Instead of subtracting/adding height to self.textView depending on whether the keyboard is shown/hidden as in the original code, the following code just calculates the maximum possible height for self.textView after subtracting the height of the keyboard on screen.

    This assumes that self.textView is suppose to fill the entire view of the view controller, and there's no other subview that needs to be visible.

    - (void)resizeTextViewWithKeyboardNotification:(NSNotification*)notif {
    
        NSDictionary* userInfo = [notif userInfo];
        NSTimeInterval animationDuration;
        UIViewAnimationCurve animationCurve;
        CGRect keyboardFrameInWindowsCoordinates;
    
        [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
        [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
        [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindowsCoordinates];
    
        [self resizeTextViewToAccommodateKeyboardFrame:keyboardFrameInWindowsCoordinates
                                 withAnimationDuration:animationDuration
                                        animationCurve:animationCurve];
    
    }
    
    - (void)resizeTextViewToAccommodateKeyboardFrame:(CGRect)keyboardFrameInWindowsCoordinates
                               withAnimationDuration:(NSTimeInterval)duration
                                      animationCurve:(UIViewAnimationCurve)curve
    {
    
        CGRect fullFrame = self.view.frame;
    
        CGRect keyboardFrameInViewCoordinates =
        [self.view convertRect:keyboardFrameInWindowsCoordinates fromView:nil];
    
        // Frame of the keyboard that intersects with the view. When keyboard is
        // dismissed, the keyboard frame still has width/height, although the origin
        // keeps the keyboard out of the screen.
        CGRect keyboardFrameVisibleOnScreen =
        CGRectIntersection(fullFrame, keyboardFrameInViewCoordinates);
    
        // Max frame availble for text view. Assign it to the full frame first
        CGRect newTextViewFrame = fullFrame;
    
        // Deduct the the height of any keyboard that's visible on screen from
        // the height of the text view
        newTextViewFrame.size.height -= keyboardFrameVisibleOnScreen.size.height;
    
        if (duration)
        {
            [UIView beginAnimations:nil context:nil];
            [UIView setAnimationDuration:duration];
            [UIView setAnimationCurve:curve];
        }
    
        // Adjust the size of the text view to the new one
        self.textView.frame = newTextViewFrame;
    
        if (duration)
        {
            [UIView commitAnimations];
        }
    
    }
    

    Also, don't forget to register the keyboard notifications in viewDidLoad:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        NSNotificationCenter* notifCenter = [NSNotificationCenter defaultCenter];
    
        [notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillShowNotification object:nil];
        [notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillHideNotification object:nil];
    }
    

    About splitting the resizing code into two parts

    The reason why the textView resizing code is split into two parts (resizeTextViewWithKeyboardNotification: and resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:) is to fix another issue when the keyboard persists through a push from one view controller to another (see How do I detect the iOS keyboard when it stays up between controllers?).

    Since the keyboard is already present before the view controller is pushed, there's no additional keyboard notifications being generated by iOS, and thus no way to resize the textView based on those keyboard notifications.

    The above code (as well as the original code) that resizes self.textView will thus only work when the keyboard is shown after the view has been loaded.

    My solution is to create a singleton that stores the last keyboard coordinates, and on - viewDidAppear: of the viewController, call:

    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
    
        // Resize the view if there's any keyboard presence before this
        // Only call in viewDidAppear as we are unable to convertRect properly
        // before view is shown
        [self resizeViewToAccommodateKeyboardFrame:[[UASKeyboard sharedKeyboard] keyboardFrame]
                             withAnimationDuration:0
                                    animationCurve:0];
    }
    

    UASKeyboard is my singleton here. Ideally we should call this in - viewWillAppear:, however in my experience (at least on iOS 6), the convertRect:fromView: method that we need to use in resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve: does not properly convert the keyboard frame to the view coordinates before the view is fully visible.

    0 讨论(0)
提交回复
热议问题