tamaño - Cubiertas de teclado para iPhone UITextField
cambiar teclado iphone 6 (20)
Tengo una aplicación donde, en Interface Builder , configuré una UIView
que tiene un campo de texto cerca de la parte inferior de la vista. Cuando ejecuto la aplicación y trato de ingresar texto en ese campo, el teclado se desliza hacia arriba del campo para que no pueda ver lo que estoy escribiendo hasta que vuelva a ocultar el teclado.
¿Alguien más se ha encontrado con este problema y ha encontrado una buena manera de resolverlo sin hacer que la vista padre sea desplazable o mover el campo de texto más arriba en la pantalla?
¿Cómo manejas la situación donde el teclado está arriba y el marco ha cambiado de tamaño con la animación y se desplazó para que el campo de texto no esté cubierto, a partir de ahí cuando selecciono otro campo de texto (aún editando el primer campo de texto) cómo no reproduzco la animación otra vez solo desplazarse un poco más si es necesario? El problema es reproducir toda la animación cuando no es necesario. Gracias
¿Qué hay de la solución oficial: Mover el contenido que se encuentra debajo del teclado
El ajuste de su contenido generalmente implica cambiar el tamaño temporalmente de una o más vistas y colocarlas de manera que el objeto de texto permanezca visible. La forma más sencilla de administrar objetos de texto con el teclado es insertarlos dentro de un objeto UIScrollView (o una de sus subclases como UITableView). Cuando se muestra el teclado, todo lo que tiene que hacer es reiniciar el área de contenido de la vista de desplazamiento y desplazar el objeto de texto deseado a su posición. Por lo tanto, en respuesta a un UIKeyboardDidShowNotification, su método de manejo haría lo siguiente:
- Obtenga el tamaño del teclado.
- Ajuste la inserción de contenido inferior de su vista de desplazamiento por la altura del teclado.
- Desplace el campo de texto de destino a la vista.
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it''s visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
A continuación se muestra una versión rápida de la respuesta de Amagrammer. Además, una variación con el evento UIKeyboardWillShowNotification ya que necesitaba saber el tamaño de los teclados antes de mover la vista fuera del camino.
var keyboardHeight:CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChange:", name: UIKeyboardWillShowNotification, object: nil)
}
func textFieldDidBeginEditing(textField: UITextField) {
//keyboardWillChange (below) is used instead of textFieldDidBeginEditing because textFieldDidBeginEditing
//is called before the UIKeyboardWillShowNotification necessary to determine the keyboard height.
}
func textFieldDidEndEditing(textField: UITextField) {
animateTextField(false)
}
func animateTextField(textFieldUp:Bool) {
let movementDistance:CGFloat = keyboardHeight
let movementDuration = 0.3
let movement:CGFloat = (textFieldUp ? -movementDistance : movementDistance)
UIView.beginAnimations("anim", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration)
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
UIView.commitAnimations()
}
func keyboardWillChange(notification:NSNotification) {
let keyboardRect:CGRect = ((notification.userInfo![UIKeyboardFrameEndUserInfoKey])?.CGRectValue)!
keyboardHeight = keyboardRect.height
animateTextField(true)
}
Además de la solución de Amagrammer, si está utilizando cocos2d en modo retrato, cambie esta línea:
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
a esto:
[CCDirector sharedDirector].openGLView.frame = CGRectOffset([CCDirector sharedDirector].openGLView.frame, movement, 0);
Si está utilizando cocos2d en modo horizontal, haga que lo anterior cambie y cambie los valores textFieldDidBeginEditing:
en textFieldDidBeginEditing:
y textFieldDidEndEditing:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self animateTextField:textField up:NO];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self animateTextField:textField up:YES];
}
Aquí hay una solución que usa Xcode5, iOS7:
Utilice el UITextfieldDelegate y los bloques de animación.
Esto es casi todo el código para ViewController, pero quería incluir el código de delegado para aquellos que todavía no están familiarizados con el patrón de delegado (como yo). También incluí código para ocultar el teclado cuando tocas lejos de la vista de texto.
Puede mover las vistas (botones, campos de texto, etc.) tan alto como desee, solo asegúrese de volver a colocarlas en su lugar (+100 y luego -100).
@interface ViewController () <UITextFieldDelegate>
@property (strong, nonatomic) IBOutlet UITextField *MyTextField;
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.MyTextField.delegate = self;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(@"text began editing");
CGPoint MyPoint = self.MyTextField.center;
[UIView animateWithDuration:0.3
animations:^{
self.MyTextField.center = CGPointMake(MyPoint.x, MyPoint.y - 100);
}];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
NSLog(@"text ENDED editing");
CGPoint MyPoint = self.MyTextField.center;
[UIView animateWithDuration:0.3
animations:^{
self.MyTextField.center = CGPointMake(MyPoint.x, MyPoint.y + 100);
}];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.view endEditing:YES];
}
Arrastrar y soltar el marco que utilizo en mis proyectos. Admite la eliminación automática cuando toca fuera de un primer respondedor o cuando se desplaza.
Creo en las versiones más nuevas de iOS (6.1+, posiblemente incluso antes), la vista subyacente, al menos para UITableView, se contrae automáticamente cuando aparece el teclado. Entonces solo necesita hacer que el campo de texto sea visible en esa vista. En init
:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
entonces:
- (void)keyboardWasShown:(NSNotification*)notification
{
// Scroll the text field into view so it''s not under the keyboard.
CGRect rect = [self.tableView convertRect:inputView.bounds fromView:inputView];
[self.tableView scrollRectToVisible:rect animated:YES];
}
Esto funcionó de maravillas para mí deslizando uitextfields
En particular, tiene el beneficio de calcular la distancia de animación de diapositivas dependiendo de la posición del campo de texto.
Hubo un gran tutorial en la edición de campos de texto sin oscurecer (link dead now, aquí hay un enlace de Wayback: https://web.archive.org/web/20091123074029/http://acts-as-geek.blogspot.com/2009/11/editing-textfields-without-obscuring.html ). Muestra cómo mover una UIView
existente en UIScrollView
, y desplazarse automáticamente cuando aparece el teclado.
Lo he actualizado un poco para calcular la altura correcta para el UIScrollView
cuando hay controles (como una UITabBar
) debajo de UIScrollBar
. Ver la publicación de la actualización de uiview .
La solución habitual es deslizar el campo (y todo lo que está sobre él) hacia arriba con una animación, y luego volver a bajar cuando haya terminado. Es posible que deba colocar el campo de texto y algunos de los otros elementos en otra vista y deslice la vista como una unidad. (Yo llamo a estas cosas "platos" como en "placas tectónicas", pero así soy yo). Pero aquí está la idea general si no necesitas ser elegante.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField: textField up: YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField: textField up: NO];
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: @"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
Me he enfrentado al mismo problema en las celdas UITableView
textField. Resuelvo este problema implementando el siguiente método para escuchar la notificación del teclado.
Observador de las notificaciones aquí:
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
Maneje esas notificaciones usando la siguiente función:
(void)keyboardWasShown:(NSNotification*)aNotification
(void)keyboardWillBeHidden:(NSNotification*)aNotification
Mira esto. Sin molestias para ti
Esta solución es muy clara. Todo lo que tiene que hacer es agregar sus campos de texto en UIScrollView
y cambiar su clase a TPKeyboardAvoidingScollView
, si está usando storyboards. La vista de desplazamiento se extiende de tal forma que detectará cuándo el teclado está visible y se moverá sobre el teclado a una distancia razonable. Es la solución perfecta porque es independiente de su UIViewController
. Todo lo necesario se hace dentro de la clase mencionada anteriormente. Gracias Michael Tyson y todo.
Para ampliar la respuesta de Amagrammer, aquí hay una clase de muestra:
LoginViewController.h
@interface LoginViewController : UIViewController <UITextFieldDelegate> {
}
@property (nonatomic, retain) IBOutlet UITextField *emailTextField;
@property (nonatomic, retain) IBOutlet UITextField *passwordTextField;
Tenga en cuenta que estamos implementando el "UITextFieldDelegate"
LoginViewController.m
@implementation LoginViewController
@synthesize emailTextField=_emailTextField;
@synthesize passwordTextField=_passwordTextField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
//Register to receive an update when the app goes into the backround
//It will call our "appEnteredBackground method
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appEnteredBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
return self;
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: @"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField: textField up: YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField: textField up: NO];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
//This is called when the app goes into the background.
//We must reset the responder because animations will not be saved
- (void)appEnteredBackground{
[self.emailTextField resignFirstResponder];
[self.passwordTextField resignFirstResponder];
}
Por favor mira mi comentario en esto:
Simplemente deslice la vista hacia arriba y hacia abajo según sea necesario:
- (void)textFieldDidEndEditing:(UITextField *)textField {
self.currentTextField = nil;
[self animateTextField: textField up: NO];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[self.currentTextField resignFirstResponder];
return YES;
}
- (void) animateTextField:(UITextField*) textField up:(BOOL)up {
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView animateWithDuration:movementDuration animations:^{
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
}];
}
No se olvide de establecerse como UITextFieldDelegate
y como el delegate
real de TextField.
(Gracias a Ammagrammer, esta es solo una respuesta más corta usando bloques para animaciones)
Supongo que una forma sería mover la posición de todas las vistas desde (x, y) a (x, y-keybaardHeight) cuando se haga clic en el campo de texto y volverlo a colocar cuando se descarte el teclado, puede parecer un poco extraño ya que la vista solo aparece (tal vez no sería malo si lo anima).
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect frame=self.view.frame;
frame.origin=CGPointMake(x...//set point here
self.view.frame=frame;
}
Tengo algo más si quieres. El punto aquí es que desea configurar el centro de su UIView en el campo de texto que está editando.
Antes de eso, debe guardar su INITIAL_CENTER , como CGPoint , desde self.view.center y su INITIAL_VIEW como CGRect desde self.view.frame en una propiedad const.
Puedes crear un método como este:
- (void) centerOn: (CGRect) fieldFrame {
// Set up the center by taking the original view center
CGPoint center = CGPointMake(INITIAL_CENTER.x,
INITIAL_CENTER.y - ((fieldFrame.origin.y + fieldFrame.size.height/2) - INITIAL_CENTER.y));
[UIView beginAnimations:@"centerViewOnField" context:nil];
[UIView setAnimationDuration:0.50];
if (CGRectEqualToRect(fieldFrame,INITIAL_VIEW)) {
self.view.frame = INITIAL_VIEW;
[self.view setCenter:INITIAL_CENTER];
} else {
[self.view setCenter:center];
}
[UIView commitAnimations];
}
Luego, en su UITextFieldDelegate , debe llamar a centerOn: (CGRect) en los siguientes métodos:
textFieldDidBeginEditing: (UITextField *) con, como parámetro, el marco del campo de texto sobre el que desea centrar.
Y tiene que llamarlo en su controlador de eventos, donde cierra el teclado,
textFieldDidEndEditing: (UITextField *) puede ser una de las formas de hacerlo, poniendo INITIAL_VIEW como un parámetro de centerOn: (CGRect) .
Tuve el mismo problema y descubrí que GTKeyboardHelper era una salida fácil.
Después de arrastrar y soltar el marco en su proyecto, incluya el archivo de encabezado. Descargue y abra el proyecto de ejemplo, luego arrastre el objeto "Ayudante de teclado" desde la sección de objetos en el xib a la sección de objetos en el constructor de interfaz de su proyecto.
Arrastra y suelta todas tus vistas para que sean elementos secundarios de "Keyboard Helper".
IQKeyboardManager hace esto por usted SIN NINGUNA LÍNEA DE CÓDIGO , solo necesita arrastrar y soltar el archivo fuente relacionado para proyectar. IQKeyboardManager también admite Device Orientation , Automatic UIToolbar Management , keyboardDistanceFromTextField y mucho más de lo que piensas.
Aquí está el diagrama de flujo de control:
Paso 1: - Se agregaron notificaciones globales de UITextField
, UITextView
y UIKeyboard
en una clase singleton. Lo llamé IQKeyboardManager .
Paso 2: si se encuentran las UIKeyboardWillShowNotification
, UITextFieldTextDidBeginEditingNotification
o UITextViewTextDidBeginEditingNotification
, intente obtener la instancia de topMostViewController
desde la jerarquía UIWindow.rootViewController
. Para descubrir adecuadamente UITextField
/ UITextView
, se debe topMostViewController.view
el marco de topMostViewController.view
.
Paso 3: - Distancia de movimiento esperada calculada de topMostViewController.view
con respecto al primer UITextField
/ UITextView
respondido.
Paso 4: movió arriba / abajo topMostViewController.view.frame
arriba / abajo según la distancia de movimiento esperada.
Paso 5: - Si se encuentra la UIKeyboardWillHideNotification
, UITextFieldTextDidEndEditingNotification
o UITextViewTextDidEndEditingNotification
, intente nuevamente obtener la instancia de topMostViewController
desde la jerarquía UIWindow.rootViewController
.
Paso 6: - Distancia perturbada calculada de topMostViewController.view
que debe restaurarse en su posición original.
Paso 7: restaurado topMostViewController.view.frame
hacia abajo según la distancia perturbada.
Paso 8: instancia de instancia Singleton IQKeyboardManager instanciada en la carga de la aplicación, por lo que cada UITextField
/ UITextView
en la aplicación se ajustará automáticamente según la distancia de movimiento esperada.
Eso es todo
https://github.com/ZulwiyozaPutra/Shift-Keyboard-Example Espero que esta solución haya sido de ayuda. Todos son Swift 3 escritos.
//
// ViewController.swift
// Shift Keyboard Example
//
// Created by Zulwiyoza Putra on 11/23/16.
// Copyright © 2016 Zulwiyoza Putra. All rights reserved.
//
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
//connecting textfield from storyboard
@IBOutlet weak var textField: UITextField!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
subscribeToKeyboardNotifications()
}
override func viewDidAppear(_ animated: Bool) {
self.textField.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
unsubscribeFromKeyboardNotifications()
}
//Hide keyboard after finished editing
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
//Setup view before keyboard appeared
func keyboardWillAppear(_ notification:Notification) {
view.frame.origin.y = 0 - getKeyboardHeight(notification)
}
//Setup view before keyboard disappeared
func keyboardWillDisappear(_ notification: Notification) {
view.frame.origin.y = 0
}
//Getting keyboard height
func getKeyboardHeight(_ notification:Notification) -> CGFloat {
let userInfo = notification.userInfo
let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue // of CGRect
return keyboardSize.cgRectValue.height
}
//Subscribing to notifications to execute functions
func subscribeToKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(_:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(_:)), name: .UIKeyboardWillHide, object: nil)
}
//Unsubscribing from notifications
func unsubscribeFromKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
}