ios - smart - Ocultar entradaAccesorioVer si el teclado de hardware está conectado
smart keyboard ipad pro no funciona (3)
Esto es solo una mejora de la respuesta de @arlomedia. Lo que hice fue observar el willShow y didShow.
El willShow que utilizo para mover mi vista de texto en posición para que se mueva a la misma velocidad que el teclado.
El didShow lo uso para verificar el tamaño aparente del teclado usando la técnica antes mencionada y ocultar / mostrar el accesorio InputView en consecuencia.
Es importante que también configure esa vista para que esté oculta por defecto, y que cuando se reciba un evento willHide, se oculte nuevamente.
- (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;
}
NOTA Editado para agregar el cambio a userInteractionEnabled para que un accesorio oculto ViewView no comience a tocar.
Similar a esta pregunta: iPad: detección de teclado externo , estoy desarrollando una aplicación de iPad que está usando campos de texto con una inputAccessoryView
de inputAccessoryView
de inputAccessoryView
personalizada para proporcionar funcionalidad adicional para el teclado virtual.
Sin embargo, si un teclado de hardware (por ejemplo, un teclado bluetooth) está conectado al dispositivo, el teclado del software no se muestra como se esperaba, pero por alguna razón, la entrada AccessWindowView todavía está visible en la parte inferior de la pantalla. Además, esto parece provocar la activación de UIKeyboardDidShowNotification
(y, por lo tanto, mover mi vista hacia arriba para evitar la oclusión del teclado, que en realidad no está presente), incluso si el teclado de hardware se utiliza para la entrada.
Encontré varias soluciones para detectar si un teclado de hardware está conectado, pero todas UIKeyboardDidShowNotification
el estado después de recibir un UIKeyboardDidShowNotification
, en cuyo punto el inputAccessoryView ya está visible (por ejemplo, ¿cómo puedo detectar si un teclado externo está presente en un iPad? ) .
Estoy buscando una manera de mostrar solo un inputAccessoryView si no hay un teclado de hardware conectado. Por lo tanto, necesito saber si un teclado de hardware está conectado antes de que se UIKeyboardDidShowNotification
un UIKeyboardDidShowNotification
.
Las soluciones aceptadas aquí ¿Cómo puedo detectar si un teclado externo está presente en un iPad? no son una opción para mí, ya que utilizan API privadas que pueden hacer que mi aplicación sea rechazada.
Mi última forma de resolver este problema fue simplemente agregar un observador para el UIKeyboardWillShowNotification
...
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
.. y ocultar el inputAccessoryView
previamente almacenado en una variable de instancia.
// 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;
}
}
Resultó que el problema se debía a que yo creaba dinámicamente el inputAccessoryView
de mi subclase personalizada UITextField
en su método getter. Recreé inadvertidamente la vista con cada llamada del getter en lugar de reutilizar una variable de instancia con instanciación lenta. Como resultado, se ignoraron todas mis asignaciones a la vista, ya que aparentemente el método getter se invocará varias veces cuando se acceda al campo de texto y se muestre el teclado y, por lo tanto, la vista se anula después de mis asignaciones. Reutilizar la vista guardándola en una variable de instancia solucionó este problema.
IIRC, las vistas no cambian de tamaño cuando aparece el teclado del software. Estoy cambiando el tamaño de mis vistas en un método keyboardDidShow desencadenado por una notificación UIKeyboardDidShow. Por lo tanto, debería ser suficiente detectar el hardware frente al teclado del software en ese método y luego omitir el cambio de tamaño de la tabla y ocultar la vista de accesorios de entrada (o ajustar el tamaño de la tabla para acomodar la vista de accesorios de entrada, si prefiere dejar eso visible )
Para cambiar el tamaño de las vistas correctamente si hay o no un teclado de hardware, adapté el código de esta respuesta :
- (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
}
Eso es todo lo que necesita si desea dejar visible la entrada AccessoryView. Para ocultar eso, creo que necesitarás establecer una variable de instancia para que puedas acceder a ella en 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
}