IOS: get the keyboard top point in iPad view?

I need to customize the "message bar" when the keyboard is displayed and am having problems using an iPad modal controller. The "message strip" should sit right above the keyboard when it is displayed, and then at the bottom of the modal when the keyboard is hidden (application style "Messages applications").

The problem is I need to get the very top of the keyboard frame in terms of the modal coordinate system. I found this answer, which appears to be correct in theory, but does not work ( How can I find the part of my view that is not covered by the keyboard (UIModalPresenationStyleFormSheet)? )

FYI When the keyboard is displayed, the keyboard frame in the main window (ie, "keyboardFrame") = (-84.0, 526.0, 768.0, 264.0). Keyboard frame when translating for the coordinate system of the modal view controller (i.e. 'NewSize') = (-168.0, 292.0, 768.0, 264.0) *

// Convert the keyboard rect into the view controller coordinate system
// The fromView: nil means keyboardRect is in the main window coordinate system
let newSize = self.view.convertRect(keyboardFrame, fromView: nil)

// And then this is the part that gets covered!
let keyboardCoveredHeight = self.view.bounds.height - newSize.origin.y
self.messageToolbar.bottomConstraint.constant = -keyboardCoveredHeight

      

enter image description here

+3


source to share


2 answers


I ended up using a familiar category to get the correct keyboard frame in iPad view:

- (CGFloat)heightCoveredByKeyboardOfSize:(CGSize)keyboardSize
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
CGRect frameInWindow = [self convertRect:self.bounds toView:nil];
CGRect windowBounds = self.window.bounds;

CGFloat keyboardTop;
CGFloat heightCoveredByKeyboard;

//Determine height of the view covered by the keyboard relative to current rotation

switch (orientation)
{
    case UIInterfaceOrientationLandscapeLeft:
    case UIInterfaceOrientationLandscapeRight:
        keyboardTop = windowBounds.size.height - keyboardSize.height;
        heightCoveredByKeyboard = windowBounds.size.height - frameInWindow.origin.y - keyboardTop;
        break;
    case UIInterfaceOrientationPortraitUpsideDown:
    default:
        keyboardTop = windowBounds.size.height - keyboardSize.height;
        heightCoveredByKeyboard = CGRectGetMaxY(frameInWindow) - keyboardTop;
        break;
}

return MAX(0.0f,heightCoveredByKeyboard);
}

      



along with DAKeyboardControl (for panning):

    // Use [unowned self] in closure for weak reference
    self.view.addKeyboardPanningWithFrameBasedActionHandler(nil, constraintBasedActionHandler: { [unowned self] (keyboardFrameInView, opening, closing) -> Void in
        if opening
        {
            if UIDevice.isIpad()
            {
                // iPad requires a different method due to use of modal view
                self.messageToolbar.bottomConstraint.constant = -self.view.heightCoveredByKeyboardOfSize(keyboardFrameInView.size)
            }
            else
            {
                self.messageToolbar.bottomConstraint.constant = -keyboardFrameInView.size.height
            }
        }

        if closing
        {
            self.messageToolbar.bottomConstraint.constant = 0
        }

        self.view.updateConstraintsIfNeeded()
        self.view.layoutIfNeeded()
    })

      

0


source


I think you are facing one of two problems (possibly both):

  • In iOS 8, you need to convert the direct keyboard from screen coordinate space.
  • On iPad, the sheet view sometimes enlarges slightly when the keyboard is displayed, which happens after showing the keyboard, so you need to calculate the results again in viewWillLayoutSubviews

Here's a sample project that does what you want .



For posterity, here's the interesting source code:

class TypingViewController: UIViewController {

    var keyboardHoverView: UIView! // your keyboard toolbar or whatever
    var lastKeyboardFrame : CGRect! // whenever you get a frame update, store it here

    override func viewDidLoad() {
        super.viewDidLoad()

        createKeyboardHoverView()
        observeKeyboard()
    }

    func createKeyboardHoverView() {
        // make your keyboard toolbar
        keyboardHoverView = view
    }

    func observeKeyboard() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
    }

    func keyboardWillShow(notification : NSNotification) {
        let dict = notification.userInfo!
        let frameValue = dict[UIKeyboardFrameEndUserInfoKey] as! NSValue
        lastKeyboardFrame = frameValue.CGRectValue()

        moveKeyboardView()
    }

    func keyboardWillHide(notification : NSNotification) {
        moveKeyboardView()
    }

    override func viewWillLayoutSubviews() {
        // this moves the view again, in case the modal view has shifted up
        moveKeyboardView()
    }

    func moveKeyboardView() {
        if lastKeyboardFrame != nil {
            // this conversion is used in iOS 8 and differs from most online tutorials
            let frameInThisView = self.view.convertRect(lastKeyboardFrame, fromCoordinateSpace: view.window!.screen.coordinateSpace)

            var newRect = keyboardHoverView.frame
            newRect.origin.y = frameInThisView.origin.y - CGRectGetHeight(newRect)
            keyboardHoverView.frame = newRect

            println("Setting rect: \(newRect)")
        }
    }
}

      

0


source







All Articles