Capas de teclado para iPhone UITextField

Eu tenho um aplicativo onde, no Interface Builder , eu configurei um UIView que tem um campo de texto perto da parte inferior da exibição. Quando executo o aplicativo e tento inserir texto nesse campo, o teclado desliza para cima do campo, de modo que não consigo ver o que estou digitando até ocultar o teclado novamente.

Alguém mais se deparou com esse problema e encontrou uma boa maneira de resolvê-lo sem tornar a exibição dos pais rolável ou movendo o campo de texto mais para cima na canvas?

A solução usual é deslizar o campo (e tudo acima dele) com uma animação e, em seguida, recuar quando terminar. Pode ser necessário colocar o campo de texto e alguns dos outros itens em outra exibição e deslizar a exibição como uma unidade. (Eu chamo essas coisas de “pratos” como em “placas tectônicas”, mas isso é só comigo). Mas aqui está a idéia geral, se você não precisa se interessar.

 - (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]; } 

Isso funcionou maravilhas para mim deslizando uitextfields

Em particular, ele tem o benefício de calcular a distância da animação do slide, dependendo da posição do campo de texto.

IQKeyboardManager fazer isso por você com nenhuma linha de código , só precisa arrastar e soltar o arquivo de origem relacionada ao projeto. O IQKeyboardManager também suporta Orientação de Dispositivos , Gerenciamento Automático de UIToolbar , keyboardDistanceFromTextField e muito mais do que você imagina.

insira a descrição da imagem aqui

Aqui está o Fluxograma de Controle: Fluxograma de Controle

Passo 1: – Adicionado notifications globais de UITextField , UITextView e UIKeyboard em uma class singleton. Eu chamei de IQKeyboardManager .

Passo 2: – Se UIKeyboardWillShowNotification encontradas as UIKeyboardWillShowNotification , UITextFieldTextDidBeginEditingNotification ou UITextViewTextDidBeginEditingNotification , tente obter a instância UIWindow.rootViewController hierarquia UIWindow.rootViewController . Para descobrir corretamente o UITextField / UITextView , o frame topMostViewController.view precisa ser ajustado.

Passo 3: – Calculado distância de movimento esperada de topMostViewController.view em relação ao primeiro respondido UITextField / UITextView .

Passo 4: – Movido o topMostViewController.view.frame cima / baixo de acordo com a distância de movimento esperada.

Passo 5: – Se for encontrada a UIKeyboardWillHideNotification , UITextFieldTextDidEndEditingNotification ou UITextViewTextDidEndEditingNotification , tente novamente obter a instância UIWindow.rootViewController hierarquia UIWindow.rootViewController .

Passo 6: – Distância perturbada calculada de topMostViewController.view que precisa ser restaurada para sua posição original.

Passo 7: – Restaurou topMostViewController.view.frame para baixo de acordo com a distância perturbada.

Etapa8: Instância da class IQKeyboardManager singleton no carregamento do aplicativo, para que cada UITextField / UITextView no aplicativo seja ajustado automaticamente de acordo com a distância de movimento esperada.

Isso é tudo

Para expandir a resposta do Amagrammer, aqui está uma class de amostra:

LoginViewController.h

 @interface LoginViewController : UIViewController  { } @property (nonatomic, retain) IBOutlet UITextField *emailTextField; @property (nonatomic, retain) IBOutlet UITextField *passwordTextField; 

Observe que estamos implementando o “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]; } 

Como sobre a solução oficial: Movendo o conteúdo que está localizado sob o teclado

Ajustar seu conteúdo geralmente envolve resize temporariamente uma ou mais vistas e posicioná-las de modo que o object de texto permaneça visível. A maneira mais simples de gerenciar objects de texto com o teclado é incorporá-los dentro de um object UIScrollView (ou uma de suas subclasss, como UITableView). Quando o teclado é exibido, tudo o que você precisa fazer é redefinir a área de conteúdo da visualização de rolagem e rolar o object de texto desejado para a posição. Assim, em resposta a um UIKeyboardDidShowNotification, seu método manipulador faria o seguinte:

  1. Obter o tamanho do teclado.
  2. Ajuste a parte inferior do conteúdo inferior da sua vista de rolagem pela altura do teclado.
  3. Role o campo de texto de destino para a exibição.
 // 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; } 

Eu enfrento o mesmo problema em células textField UITableView . Eu resolvo esse problema implementando o seguinte método para ouvir a notificação do teclado.

Observador para as notifications aqui:

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

Lidar com essas notifications usando abaixo da function:

 (void)keyboardWasShown:(NSNotification*)aNotification (void)keyboardWillBeHidden:(NSNotification*)aNotification 

Veja isso. Sem problemas para você.

Esta solução é muito legal. Tudo o que você precisa fazer é adicionar seus TPKeyboardAvoidingScollView de TPKeyboardAvoidingScollView em um UIScrollView e alterar sua class para TPKeyboardAvoidingScollView , se estiver usando storyboards. A vista de rolagem é estendida de tal forma que detectaria quando o teclado é visível e se moverá sobre o teclado a uma distância razoável. É a solução perfeita porque é independente do seu UIViewController . Cada coisa necessária é feita dentro da class acima mencionada. Obrigado Michael Tyson et all.

TPKeyboardAvoiding

Abaixo está uma versão rápida da resposta do Amagrammer. Além disso, uma variação usando o evento UIKeyboardWillShowNotification desde que eu precisava saber o tamanho dos teclados antes de mover a vista para fora do caminho.

 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) } 

Houve um grande passo a passo na edição de campos de texto sem obscurecer (link morto agora, aqui está um link de Wayback: https://web.archive.org/web/20091123074029/http://acts-as-geek.blogspot.com/2009/ 11 / editing-textfields-without-obscuring.html ). Ele mostra como mover um UIView existente para um UIScrollView e rolá-lo automaticamente quando o teclado aparecer.

Eu atualizei um pouco para calcular a altura correta para o UIScrollView quando existem controles (como um UITabBar ) abaixo do UIScrollBar . Veja postar atualizando uiview .

Aqui está uma solução usando o Xcode5, iOS7:

Use os blocos UITextfieldDelegate e animação.

Este é quase todo o código para o ViewController, mas eu queria include o código de delegado para aqueles ainda pouco familiarizados com o padrão de delegado (como eu). Eu também incluí código para esconder o teclado quando você toca longe da visão de texto.

Você pode mover os pontos de vista (botões, campos de texto, etc) tão alto quanto quiser, apenas certifique-se de colocá-los de volta no lugar (+100 depois mais tarde -100).

 @interface ViewController ()  @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]; } 

Eu acho que uma maneira seria mover toda a sua posição de views de (x, y) para (x, y-keybaardHeight) quando o campo de texto é clicado e colocá-lo de volta quando o teclado é dispensado, pode parecer um pouco estranho surge (talvez não seja ruim se você animar).

 - (void)textFieldDidBeginEditing:(UITextField *)textField { CGRect frame=self.view.frame; frame.origin=CGPointMake(x...//set point here self.view.frame=frame; } 

Além da solução do Amagrammer, se você estiver usando o cocos2d no modo retrato, altere esta linha:

 self.view.frame = CGRectOffset(self.view.frame, 0, movement); 

para isso:

 [CCDirector sharedDirector].openGLView.frame = CGRectOffset([CCDirector sharedDirector].openGLView.frame, movement, 0); 

Se você estiver usando o cocos2d no modo paisagem, faça a alteração acima e altere os valores para up em textFieldDidBeginEditing: e textFieldDidEndEditing:

 - (void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField:textField up:NO]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField:textField up:YES]; } 

Eu tive o mesmo problema e achei o GTKeyboardHelper uma saída fácil.

Depois de arrastar e soltar o framework em seu projeto, inclua o arquivo de header. Faça o download e abra o projeto de exemplo e, em seguida, arraste o object “Assistente de Teclado” da seção de objects no xib para a seção de objects no construtor de interface do seu projeto.

Arraste e solte todos os seus pontos de vista para serem filhos do “Assistente de teclado”.

Como você lida com a situação em que o teclado está levantado e o quadro foi redimensionado com animação e rolado para que o campo de texto não seja coberto, a partir daí seleciono outro campo de texto (ainda editando o primeiro campo de texto) como reproduzir a animação novamente basta rolar um pouco mais, se necessário? O problema é reproduzir toda a animação quando ela não precisa. obrigado

Arraste e solte a estrutura que eu uso em meus projetos. Suporta demissão automática quando você toca fora de um socorrista ou quando você rola.

GTKeyboardHelper

Por favor, olhe meu comentário neste:

iPhone – Teclado esconde TextField

Basta deslizar a vista para cima e para baixo conforme necessário:

 - (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); }]; } 

Não se esqueça de definir self como um UITextFieldDelegate e como o delegate textField real.

(Graças ao Ammagrammer, esta é apenas uma resposta mais curta usando blocos para animações)

Eu tenho outra coisa, se você quiser. O ponto aqui é que você quer definir o centro do seu UIView no campo de texto que você está editando.

Antes disso, você tem que salvar seu INITIAL_CENTER , como um CGPoint , de self.view.center e seu INITIAL_VIEW como um CGRect de self.view.frame em uma propriedade const.

Você pode criar um 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]; } 

Então, no seu UITextFieldDelegate , você precisa chamar centerOn: (CGRect) nos seguintes methods:

textFieldDidBeginEditing: (UITextField *) com, como parâmetro, o quadro do campo de texto que você deseja centralizar.

E você tem que chamá-lo em seu manipulador de events, onde você fecha o teclado,

textFieldDidEndEditing: (UITextField *) pode ser uma das maneiras de fazer isso, colocando o INITIAL_VIEW como um parâmetro de centerOn: (CGRect) .

Acredito em versões mais recentes do iOS (6.1+, possivelmente até mais antigas), a visualização subjacente, pelo menos para UITableView, diminui automaticamente quando o teclado aparece. Então você só precisa tornar o campo de texto visível nessa visão. No init :

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; 

então:

 - (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]; } 

https://github.com/ZulwiyozaPutra/Shift-Keyboard-Example Espero que esta solução tenha ajudado. Eles são todos 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) } }