Hide inputAccessoryView if hardware keyboard is connected

Similar to this question: iPad: detecting an external keyboard , I am developing an application for the iPad that uses custom text fields inputAccessoryViewto provide additional functionality for the virtual keyboard.

However, if a hardware keyboard (such as a bluetooth keyboard) is connected to the device, the software keyboard does not display as expected, but for some reason, the AccessViewView input view is still displayed at the bottom of the screen. Also, this seems to trigger shooting UIKeyboardDidShowNotification(and therefore moving my view to avoid keyboard occlusion, which is actually missing), even if the hardware keyboard is used for input.

I have found a few solutions to detect if the connected hardware keyboard, but they check the condition after the receipt UIKeyboardDidShowNotification, after which InputAccessoryView element already displayed (eg, How to determine whether an external keyboard on the iPad is present? .

I am looking for a way to show only the AccessAccessoryView input interface if there is no hardware keyboard connected. So I need to know if the hardware keyboard is connected to a UIKeyboardDidShowNotification.

The decisions made here How can I determine if an external keyboard is present on the iPad? there is no choice for me, because they use private APIs that can cause my application to be rejected.

+4
source share
3 answers

My last way to solve this problem was to simply add an observer for UIKeyboardWillShowNotification...

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification object:nil];

.. and hide inputAccessoryViewpreviously stored in the instance variable.

// Called when the UIKeyboardWillShowNotification is sent.
- (void)keyboardWillShow:(NSNotification*)notification
{
    NSLog(@"keyboardWillShow");

    // get the frame end user info key
    CGRect kbEndFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    // calculate the visible portion of the keyboard on the screen
    CGFloat height = [[UIScreen mainScreen] bounds].size.height - kbEndFrame.origin.y;

    // check if there is a input accessorry view (and no keyboard visible, e.g. hardware keyboard)
    if (self.activeTextField && height <= self.activeTextField.inputAccessoryView.frame.size.height) {

        NSLog(@"hardware keyboard");

        self.activeTextField.inputAccessoryView.hidden = YES;
    } else {

        NSLog(@"software keyboard");

        self.activeTextField.inputAccessoryView.hidden = NO;
    }
}

, , inputAccessoryView UITextField getter. . , , , -, getter , , , , overridden . , , .

0

@arlomedia. , , willShow didShow.

willShow, , , , .

didShow / accessInputView .

, , , willHide, .

- (void) addKeyboardObserver {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHidden:) name:UIKeyboardWillHideNotification object:nil];
}

- (void) removeKeyboardObserver {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification*)notification {
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    // If we're on iOS7 or earlier and landscape then the height is in the
    // width.
    //
    if ((IS_LANDSCAPE == YES) && (IS_IOS8_OR_LATER == NO)) {
        keyboardSize.height = keyboardSize.width;
    }

    NSNumber *rate = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];

    CGRect textFieldFrame = self.textField.frame;
    textFieldFrame.origin.y = ([Util screenHeight] - keyboardSize.height) - textFieldFrame.size.height - [Util scaledHeight:10.0];

    // Move the text field into place.
    //
    [UIView animateWithDuration:rate.floatValue animations:^{
        self.answerTextField.frame = textFieldFrame;
    }];

    keyboardShown = YES;
}

- (void)keyboardDidShow:(NSNotification*)notification {
    CGRect keyboardBeginFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect keyboardEndFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGSize keyboardSize = keyboardBeginFrame.size;

    // If we're on iOS7 or earlier and landscape then the height is in the
    // width.
    //
    if ((IS_LANDSCAPE == YES) && (IS_IOS8_OR_LATER == NO)) {
        keyboardSize.height = ABS(keyboardBeginFrame.origin.x - keyboardEndFrame.origin.x); // the keyboard will move by an amount equal to its height when it appears; ABS is needed for upside-down orientations
    } else {
        keyboardSize.height = ABS(keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y); // the keyboard will move by an amount equal to its height when it appears; ABS is needed for upside-down orientations
    }

    NSNumber *rate = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];

    [UIView animateWithDuration:rate.floatValue animations:^{
        if (keyboardSize.height <= self.accessoryBar.frame.size.height) {
            self.textField.inputAccessoryView.hidden = YES;
            self.answerTextField.inputAccessoryView.userInteractionEnabled = NO;
        } else {
            self.textField.inputAccessoryView.hidden = NO;
            self.answerTextField.inputAccessoryView.userInteractionEnabled = YES;
        }
    }];

    keyboardShown = YES;
}

- (void)keyboardHidden:(NSNotification*)notification {

    NSNumber *rate = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];

    // Remove/hide the accessory view so that next time the text field gets focus, if a hardware
    // keyboard is used, the accessory bar is not shown.
    //
    [UIView animateWithDuration:rate.floatValue animations:^{
        self.textField.inputAccessoryView.hidden = YES;
        self.answerTextField.inputAccessoryView.userInteractionEnabled = NO;
    }];

    keyboardShown = NO;
}

userInteractionEnabled, .

+4

IIRC, . keyboardDidShow, UIKeyboardDidShow. , , ( , ).

, , :

- (void)keyboardDidShow:(NSNotification *)aNotification {
    CGRect keyboardBeginFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect keyboardEndFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    float keyboardHeight = ABS(keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y); // the keyboard will move by an amount equal to its height when it appears; ABS is needed for upside-down orientations

    // now you can resize your views based on keyboardHeight
    // that will be the height of the inputAccessoryView if a hardware keyboard is present
}

This is all you need if you want the AccessView input window to be visible. To hide this, I think you need to set the instance variable so that you can access it in keyboardDidShow:

UIView *currentInputAccessoryView;

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    self.currentInputAccessoryView = textField.inputAccessoryView;
}

- (void)textViewDidBeginEditing:(UITextView *)textView {
    self.currentInputAccessoryView = textView.inputAccessoryView;
}

- (void)keyboardDidShow:(NSNotification *)aNotification {
    CGRect keyboardBeginFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect keyboardEndFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    float keyboardHeight = ABS(keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y); // the keyboard will move by an amount equal to its height when it appears; ABS is needed for upside-down orientations

    if (keyboardHeight == 44) {
        self.currentInputAccessoryView.hidden = YES;
        keyboardHeight = 0;
    }

    // now you can resize your views based on keyboardHeight
    // that will be 0 if a hardware keyboard is present
}
+2
source

Source: https://habr.com/ru/post/1570377/


All Articles