objective-c - ios create framework
IU evitación del teclado y diseño automático (6)
Dado el enfoque en el diseño automático en iOS 6 y la recomendación de los ingenieros de Apple ( ver videos de WWDC 2012 ) de que ya no manipulamos el marco de una vista directamente, ¿cómo se evitaría usar el teclado utilizando solo diseño automático y NSLayoutConstraint?
Actualizar
Esto parece una solución razonable: un ejemplo de diseño sensible al teclado ( fuente GitHub) pero un problema potencial que veo es ¿qué sucede cuando un usuario gira el dispositivo y el teclado ya está en la pantalla?
Para el diseño automático con la caja del teclado, utilizo la vista de tabla estática. Esto mantiene sus códigos mucho más simples y no necesita realizar un seguimiento de la altura del teclado. Una cosa que aprendí sobre la vista de tabla es mantener cada fila de la tabla lo más estrecha posible. Si coloca demasiadas UI verticalmente en una fila, es posible que se superponga el teclado.
Mi idea es crear una UIView
, llamémosla vista de teclado , y colocarla en la vista del controlador de vista. Luego observe las notificaciones de cambio de marco del teclado UIKeyboardDidChangeFrameNotification
y UIKeyboardDidChangeFrameNotification
coincidir el marco del teclado con la vista del teclado (recomiendo animar el cambio). Al observar esta notificación, se maneja la rotación mencionada y también se mueve el teclado en el iPad.
Entonces simplemente crea tus restricciones relativas a esta vista del teclado . No olvides agregar la restricción a su supervista común.
Para hacer que el marco del teclado se traduzca y gire correctamente a sus coordenadas de vista, consulte los documentos de UIKeyboardFrameEndUserInfoKey
.
Creé una vista como esta que miraba el teclado y cambiaba sus propias limitaciones cuando el teclado se enciende / apaga.
@interface YMKeyboardLayoutHelperView ()
@property (nonatomic) CGFloat desiredHeight;
@property (nonatomic) CGFloat duration;
@end
@implementation YMKeyboardLayoutHelperView
- (id)init
{
self = [super init];
if (self) {
self.translatesAutoresizingMaskIntoConstraints = NO;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:@"UIKeyboardWillShowNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:@"UIKeyboardWillHideNotification" object:nil];
}
return self;
}
- (void)keyboardWillShow:(NSNotification *)notification
{
// Save the height of keyboard and animation duration
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardRect = [userInfo[@"UIKeyboardBoundsUserInfoKey"] CGRectValue];
self.desiredHeight = CGRectGetHeight(keyboardRect);
self.duration = [userInfo[@"UIKeyboardAnimationDurationUserInfoKey"] floatValue];
[self setNeedsUpdateConstraints];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
// Reset the desired height (keep the duration)
self.desiredHeight = 0.0f;
[self setNeedsUpdateConstraints];
}
- (void)updateConstraints
{
[super updateConstraints];
// Remove old constraints
if ([self.constraints count]) {
[self removeConstraints:self.constraints];
}
// Add new constraint with desired height
NSString *constraintFormat = [NSString stringWithFormat:@"V:[self(%f)]", self.desiredHeight];
[self addVisualConstraints:constraintFormat views:@{@"self": self}];
// Animate transition
[UIView animateWithDuration:self.duration animations:^{
[self.superview layoutIfNeeded];
}];
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
He escrito una biblioteca que lo hará todo por usted (admite Diseño automático y resortes y puntales)
IHKeyboardAvoiding https://github.com/IdleHandsApps/IHKeyboardAvoiding
Simplemente llame a [IHKeyboardAvoiding setAvoidingView: self.myView];
Usar el KeyboardLayoutConstraint en el marco de Spring es la solución más simple que he encontrado hasta ahora.
Esa publicación en el blog es excelente, pero me gustaría sugerir algunas mejoras. En primer lugar, puede registrarse para observar los cambios en el marco, por lo que no necesita registrarse para observar las notificaciones de Mostrar y Ocultar. En segundo lugar, debe convertir los CGRects para el teclado de la pantalla para ver las coordenadas. Por último, puede copiar la curva de animación exacta utilizada por iOS para el teclado, de modo que el teclado y las vistas de seguimiento se muevan en sincronía.
Poniéndolo todo junto, obtienes lo siguiente:
@interface MyViewController ()
// This IBOutlet holds a reference to the bottom vertical spacer
// constraint that positions the "tracking view",i.e., the view that
// we want to track the vertical motion of the keyboard
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomVerticalSpacerConstraint;
@end
@implementation MyViewController
-(void)viewDidLoad
{
[super viewDidLoad];
// register for notifications about the keyboard changing frame
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillChangeFrame:)
name:UIKeyboardWillChangeFrameNotification
object:self.view.window];
}
-(void)keyboardWillChangeFrame:(NSNotification*)notification
{
NSDictionary * userInfo = notification.userInfo;
UIViewAnimationCurve animationCurve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] intValue];
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// convert the keyboard''s CGRect from screen coords to view coords
CGRect kbEndFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]
fromView:self.view.window];
CGRect kbBeginFrame = [self.view convertRect:[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]
fromView:self.view.window];
CGFloat deltaKeyBoardOrigin = kbEndFrame.origin.y - kbBeginFrame.origin.y;
// update the constant factor of the constraint governing your tracking view
self.bottomVerticalSpacerConstraint.constant -= deltaKeyBoardOrigin;
// tell the constraint solver it needs to re-solve other constraints.
[self.view setNeedsUpdateConstraints];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:animationCurve];
[UIView setAnimationBeginsFromCurrentState:YES];
// within this animation block, force the layout engine to apply
// the new layout changes immediately, so that we
// animate to that new layout. We need to use old-style
// UIView animations to pass the curve type.
[self.view layoutIfNeeded];
[UIView commitAnimations];
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillChangeFrameNotification
object:nil];
}
@end
Esto funcionará, siempre y cuando no cambie la orientación mientras el teclado está levantado.
Fue una respuesta sobre Cómo imitar la animación del teclado en iOS 7 para agregar el botón "Hecho" al teclado numérico? mostró cómo imitar la curva de animación del teclado correctamente.
Una última cosa a tener en cuenta con respecto a todas estas soluciones basadas en notificaciones: pueden producir efectos inesperados si alguna otra pantalla en su aplicación también usa el teclado, porque su controlador de vista seguirá recibiendo las notificaciones siempre que no se haya desasignado. , incluso si sus vistas están descargadas. Un remedio para esto es poner un condicional en el controlador de notificaciones para garantizar que solo funcione cuando el controlador de vista está en pantalla.