Com o SDK do iOS:
Eu tenho um UIView
com UITextField
s que exibem um teclado. Eu preciso que ele seja capaz de:
Permitir a rolagem do conteúdo do
UIScrollView
para ver os outros campos de texto assim que o teclado for aberto"Salte" automaticamente (rolando para cima) ou diminua
Eu sei que preciso de um UIScrollView
. Tentei alterar a classe da minha UIView
para uma, UIScrollView
mas ainda não consigo rolar as caixas de texto para cima ou para baixo.
Preciso de um UIView
e de um UIScrollView
? Um entra no outro?
O que precisa ser implementado para rolar automaticamente para o campo de texto ativo?
Idealmente, o máximo possível da configuração dos componentes será feito no Interface Builder. Eu gostaria de escrever apenas o código para o que precisa.
Nota: o UIView
(ou UIScrollView
) com o qual estou trabalhando é apresentado por uma barra de tabulação ( UITabBar
), que precisa funcionar normalmente.
Editar: estou adicionando a barra de rolagem apenas para quando o teclado aparecer. Mesmo que não seja necessário, sinto que ele fornece uma interface melhor, porque então o usuário pode rolar e alterar caixas de texto, por exemplo.
Eu tenho que trabalhar onde eu altero o tamanho do quadro UIScrollView
quando o teclado sobe e desce. Estou simplesmente usando:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
//Keyboard becomes visible
scrollView.frame = CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50); //resize
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
//keyboard will hide
scrollView.frame = CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.frame.size.width,
scrollView.frame.size.height + 215 - 50); //resize
}
No entanto, isso não "move para cima" ou centraliza automaticamente os campos de texto inferiores na área visível, o que eu realmente gostaria.
fonte
Respostas:
Você só precisará de um
ScrollView
se o conteúdo que você possui agora não couber na tela do iPhone. (Se você estiver adicionando aScrollView
visão geral dos componentes apenas para fazer aTextField
rolagem para cima quando o teclado aparecer, isso não será necessário.)A maneira padrão de impedir que os
TextField
s sejam cobertos pelo teclado é mover a visualização para cima / baixo sempre que o teclado é mostrado.Aqui está um exemplo de código:
fonte
textFieldDidBeginEditing
seção.Eu também estava tendo muitos problemas com a
UIScrollView
composição de múltiplosUITextFields
, dos quais, um ou mais deles seriam obscurecidos pelo teclado durante a edição.Aqui estão algumas coisas a considerar se o seu
UIScrollView
não estiver rolando corretamente.1) Verifique se o contentSize é maior que o
UIScrollView
tamanho do quadro. A maneira de entenderUIScrollViews
é queUIScrollView
é como uma janela de visualização no conteúdo definido no contentSize. Portanto, quando forUIScrollview
para rolar para qualquer lugar, o contentSize deve ser maior que oUIScrollView
. Senão, não há rolagem necessária, já que tudo definido no contentSize já está visível. BTW, contentSize padrão =CGSizeZero
.2) Agora que você entende que
UIScrollView
realmente é uma janela para o seu "conteúdo", a maneira de garantir que o teclado não oculte suaUIScrollView's
"janela" de visualização seria redimensioná-laUIScrollView
para que, quando o teclado estiver presente, você tenha aUIScrollView
janela dimensionado para apenas oUIScrollView
frame.size.height original menos a altura do teclado. Isso garantirá que sua janela seja apenas aquela pequena área visível.3) Aqui está o problema: quando implementei isso pela primeira vez, imaginei que teria que obter o campo
CGRect
deUIScrollView's
texto editado e chamar o método scrollRecToVisible. Eu implementei oUITextFieldDelegate
métodotextFieldDidBeginEditing
com a chamada para oscrollRecToVisible
método Isso realmente trabalhou com um efeito colateral estranho que a rolagem iria tirar oUITextField
na posição. Durante muito tempo, não consegui descobrir o que era. Então eu comentei otextFieldDidBeginEditing
método Delegate e tudo funcionou !! (???). Como se viu, acredito que, naUIScrollView
verdade, implica implicitamente o atualmente editadoUITextField
na janela visível. Minha implementação doUITextFieldDelegate
método e a chamada subsequente aoscrollRecToVisible
foram redundantes e foram a causa do estranho efeito colateral.Então, aqui estão os passos para rolar adequadamente o seu
UITextField
em umUIScrollView
no lugar quando o aparece teclado.viewDidLoad
viewDidUnload
contentSize
está definido e maior do que aUIScrollView
deviewDidLoad
UIScrollView
quando o teclado está presenteUIScrollView
quando o teclado desaparecer.UITextField
é tabulado mesmo se o teclado já está presente para evitar encolhendo oUIScrollView
quando ele já está encolhidoUma coisa a ser observada é que ela
UIKeyboardWillShowNotification
será acionada mesmo quando o teclado já estiver na tela quando você tabular outraUITextField
. Eu cuidei disso usando um ivar para evitar o redimensionamento doUIScrollView
quando o teclado já está na tela. Redimensionar inadvertidamenteUIScrollView
quando o teclado já está lá seria desastroso!Espero que este código poupe muita dor de cabeça a alguns de vocês.
fonte
UIKeyboardBoundsUserInfoKey
está obsoleto. 2. keyboardSize está em "coordenadas da tela", portanto seus cálculos do viewFrame falharão se o quadro for girado ou dimensionado.CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
vez dos obsoletos #UIKeyboardBoundsUserInfoKey
[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size
deveria ser[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size
. Ótima solução!Na verdade, é melhor usar a implementação da Apple, conforme fornecido nos documentos . No entanto, o código que eles fornecem está com defeito. Substitua a parte encontrada
keyboardWasShown:
logo abaixo dos comentários pelo seguinte:Os problemas com o código da Apple são os seguintes: (1) Eles sempre calculam se o ponto está dentro do quadro da visualização, mas é um
ScrollView
, portanto, ele já pode ter sido rolado e você precisa contabilizar esse deslocamento:(2) Eles mudam o contentOffset pela altura do teclado, mas queremos o oposto (queremos mudar
contentOffset
pela altura que é visível na tela, não o que não é):fonte
UIKeyboardFrameEndUserInfoKey
vez deUIKeyboardFrameBeginUserInfoKey
obter o tamanho do teclado, pois isso inclui itens como alterações personalizadas do teclado e ativar / desativar o texto previsto.self.scrollView.contentOffset = self.currentSVoffset;
Na chamada
textFieldDidBeginEditting
e natextFieldDidEndEditing
chamada, a função[self animateTextField:textField up:YES]
é a seguinte:Espero que este código o ajude.
Em Swift 2
SWIFT 3
fonte
[UIView animateWithDuration: animations:^{ }];
?Apenas usando TextFields:
1a) Usando
Interface Builder
: Selecionar todos os campos de texto => Editar => Incorporar => ScrollView1b) Incorporar manualmente TextFields no UIScrollView chamado scrollView
2) Definir
UITextFieldDelegate
3) Defina cada
textField.delegate = self;
(ou faça as conexõesInterface Builder
)4) Copiar / colar:
fonte
textField
já está visível.CGPointMake(0, textField.frame.origin.y);
paraCGPointMake(0, textField.frame.origin.y + scrollView.contentInset.top);
Para a Universal Solution , aqui estava minha abordagem para implementar o IQKeyboardManager .
Passo 1: - Eu adicionei notificações globais de
UITextField
,UITextView
eUIKeyboard
em uma única classe. Eu chamo de IQKeyboardManager .Etapa 2: - Se encontrado
UIKeyboardWillShowNotification
,UITextFieldTextDidBeginEditingNotification
ouUITextViewTextDidBeginEditingNotification
notificações, tento obtertopMostViewController
instância daUIWindow.rootViewController
hierarquia. A fim de adequadamente uncoverUITextField
/UITextView
sobre ele,topMostViewController.view
's quadro precisa ser ajustado.Etapa 3: - Calculei a distância esperada de movimento
topMostViewController.view
em relação à primeira respostaUITextField
/UITextView
.Passo 4: - Mudei para
topMostViewController.view.frame
cima / baixo de acordo com a distância de movimento esperada.Etapa 5: - Se encontrado
UIKeyboardWillHideNotification
,UITextFieldTextDidEndEditingNotification
ouUITextViewTextDidEndEditingNotification
notificação, tento novamente obtertopMostViewController
instância daUIWindow.rootViewController
hierarquia.Passo 6: - Calculei a distância perturbada da
topMostViewController.view
qual precisa ser restaurada para sua posição original.Passo 7: - Eu restaurei de
topMostViewController.view.frame
acordo com a distância perturbada.Etapa 8: - Instanciei a instância da classe IQKeyboardManager de singleton na carga do aplicativo, para que todos
UITextField
/UITextView
no aplicativo se ajustem automaticamente de acordo com a distância de movimento esperada.Isso é tudo o que o IQKeyboardManager faz por você com NENHUMA LINHA DE CÓDIGO realmente !! só é necessário arrastar e soltar o arquivo de origem relacionado ao projeto. O IQKeyboardManager também suporta Orientação a dispositivos , Gerenciamento automático da barra de ferramentas do UIT , KeybkeyboardDistanceFromTextField e muito mais do que você pensa.
fonte
Eu coloquei um universal, drop-in
UIScrollView
,UITableView
e até mesmoUICollectionView
subclasse que cuida de mover todos os campos de texto dentro dele fora do caminho do teclado.Quando o teclado estiver prestes a aparecer, a subclasse encontrará a subvisão que está prestes a ser editada e ajustará o quadro e o deslocamento do conteúdo para garantir que a visualização seja visível, com uma animação para corresponder ao pop-up do teclado. Quando o teclado desaparece, ele restaura seu tamanho anterior.
Ele deve funcionar basicamente com qualquer configuração, seja uma
UITableView
interface baseada em ou uma que consiste em visualizações colocadas manualmente.Aqui está: solução para mover os campos de texto para fora do caminho do teclado
fonte
Isso fará tudo por você, basta colocá-los na sua classe de controlador de exibição e implementar o
UITextFieldDelegate
no seu controlador de exibição e definir o delegado do textField paraself
Implemente os métodos de retorno de chamada delegados:
Para Swift 4, 4.2, 5: Alterar
para
Última observação sobre esta implementação: Se você colocar outro controlador de exibição na pilha enquanto o teclado for mostrado, isso criará um erro no qual a exibição retornará ao quadro central, mas o deslocamento do teclado não será redefinido. Por exemplo, o teclado é o primeiro a responder ao nameField, mas você pressiona um botão que coloca o Help View Controller na pilha. Para corrigir o erro de deslocamento, chame nameField.resignFirstResponder () antes de sair do controlador de exibição, garantindo que o método delegado textFieldDidEndEditing também seja chamado. Eu faço isso no método viewWillDisappear.
fonte
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
então eu mudei essa linha paraself.view.frame.offsetInPlace(dx: 0, dy: movement)
Já existem muitas respostas, mas ainda assim nenhuma das soluções acima tinha todo o material de posicionamento necessário para uma animação "perfeita" livre de bugs, compatível com versões anteriores e sem tremulação. (erro ao animar quadros / limites e contentOffset juntos, diferentes orientações de interface, teclado dividido para iPad, ...)
Deixe-me compartilhar minha solução:
(supondo que você tenha configurado
UIKeyboardWill(Show|Hide)Notification
)fonte
UIApplication.shared.sendAction(...)
. Aqui está a versão Swift 3 de sua resposta (menos parte willHide), com asendAction
implementação: gist.github.com/xaphod/7aab1302004f6e933593a11ad8f5a72dShiun disse: "Como se viu, acredito que o UIScrollView realmente traz implicitamente o UITextField atualmente editado na janela visível implicitamente" Isso parece ser verdade para o iOS 3.1.3, mas não 3.2, 4.0 ou 4.1. Eu tive que adicionar um scrollRectToVisible explícito para tornar o UITextField visível no iOS> = 3.2.
fonte
[UITextField scrollTextFieldToVisibleIfNecessary]
método privado que, por sua vez, chama[UIScrollView scrollRectToVisible]
quando[UITextField becomeFirstResponder]
é chamado. Consulte github.com/leopatras/ios_textfields_on_scrollview . Se as restrições e os controladores de exibição estiverem configurados corretamente, não será necessário chamarscrollRectToVisible
explicitamente (pelo menos desde o IOS 11).Uma coisa a considerar é se você deseja usar um
UITextField
por conta própria. Não encontrei aplicativos para iPhone bem projetados que realmente sejam usadosUITextFields
fora deleUITableViewCells
.Será um trabalho extra, mas eu recomendo que você implemente todas as visualizações de entrada de dados em uma tabela. Adicione um
UITextView
ao seuUITableViewCells
.fonte
UITableView
infelizmente é o único caminho a percorrer. As notificações do teclado são frágeis e mudaram horas extras. Código de exemplo no estouro de pilha: stackoverflow.com/a/32390936/218152Este documento detalha uma solução para este problema. Veja o código-fonte em 'Movendo o conteúdo localizado sob o teclado'. É bem direto.
EDIT: Notei que há uma pequena falha no exemplo. Você provavelmente vai querer ouvir em
UIKeyboardWillHideNotification
vez deUIKeyboardDidHideNotification
. Caso contrário, a visualização de rolagem atrás do teclado será cortada durante a animação de fechamento do teclado.fonte
Solução mais fácil encontrada
fonte
int movement = (up ? -movementDistance : movementDistance);
if (textField.frame.origin.y < self.view.frame.size.height - keyboard.height) { movementDistance = 0 }
Por favor, não que akeyboard
variável é o CGRect do teclado que aparece que você começa fazendo:let keyboard = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey]!.CGRectValue())!
Pequena correção que funciona para muitos UITextFields
fonte
rect.origin.y=+currTextField.frame.origin.y
funcionando bem obrigadoO código do RPDP move com sucesso o campo de texto para fora do caminho do teclado. Mas quando você rolar para o topo depois de usar e descartar o teclado, o topo será rolado para cima para fora da visualização. Isso é verdade para o simulador e o dispositivo. Para ler o conteúdo na parte superior dessa visualização, é necessário recarregar a visualização.
O código a seguir não deveria trazer a visualização de volta?
fonte
Não tenho certeza se mover a visualização para cima é a abordagem correta, fiz isso de maneira diferente, redimensionando o UIScrollView. Expliquei em detalhes em um pequeno artigo
fonte
Para retornar ao estado original da visualização, adicione:
fonte
Tente este pequeno truque.
fonte
Existem muitas soluções, mas passo algumas horas antes de começar a funcionar. Então, coloquei este código aqui (basta colar no projeto, nenhuma modificação precisa):
PS: Espero que o código ajude alguém a fazer o efeito desejado rapidamente. (Xcode 4.5)
fonte
@ user271753
Para recuperar a visualização original, adicione:
fonte
Não requer uma visualização de rolagem para poder mover o quadro de visualização. Você pode alterar o quadro de uma
viewcontroller's
visualização para que a visualização inteira se mova apenas o suficiente para colocar o campo de texto do responsável pela resposta acima do teclado. Quando me deparei com esse problema, criei uma subclasseUIViewController
que faz isso. Ele observa que o teclado exibirá uma notificação e localizará a subvisão da primeira resposta e (se necessário) anima a visualização principal para cima apenas o suficiente para que a primeira resposta fique acima do teclado. Quando o teclado se oculta, ele anima a exibição de volta onde estava.Para usar esta subclasse, transforme seu controlador de exibição personalizado em uma subclasse de GMKeyboardVC e ele herda esse recurso (apenas certifique-se de implementar
viewWillAppear
eviewWillDisappear
eles devem chamar super). A classe está no github .fonte
Swift 4 .
Você pode mover-se facilmente cima e para baixo
UITextField
OuUIView
ComUIKeyBoard
ComAnimation
fonte
Aqui está a solução de hack que eu criei para um layout específico. Essa solução é semelhante à solução de Matt Gallagher, na qual é exibida uma seção. Ainda sou novo no desenvolvimento do iPhone e não estou familiarizado com o funcionamento dos layouts. Assim, este hack.
Minha implementação precisava oferecer suporte à rolagem ao clicar em um campo e também à rolagem quando o usuário seleciona o próximo no teclado.
Eu tinha um UIView com uma altura de 775. Os controles estão espalhados basicamente em grupos de 3 em um espaço grande. Acabei com o seguinte layout IB.
Aí vem o hack
Defino a altura do UIScrollView para 500 unidades maiores que o layout real (1250). Criei uma matriz com as posições absolutas para as quais preciso rolar e uma função simples para obtê-las com base no número da etiqueta IB.
Agora, tudo o que você precisa fazer é usar as duas linhas de código a seguir em textFieldDidBeginEditing e textFieldShouldReturn (a última se você estiver criando uma próxima navegação de campo)
Um exemplo.
Este método não 'retrocede' como outros métodos. Isso não era um requisito. Novamente, isso foi para uma UIView razoavelmente "alta" e eu não tive dias para aprender os mecanismos de layout interno.
fonte
De acordo com os documentos , no iOS 3.0, a
UITableViewController
classe redimensiona e reposiciona automaticamente sua exibição de tabela quando há edição em linha de campos de texto. Eu acho que não é suficiente colocar o campo de texto dentro de um,UITableViewCell
como alguns indicaram.Dos documentos :
fonte
Você precisa apenas copiar e colar o código de exemplo abaixo e alterar seu campo de texto ou qualquer visualização que queira mover para cima.
Passo 1
Passo 2
Etapa 3
Referência : bem, por favor , aprecie esse cara , que compartilhou esse belo código, solução limpa.
Espero que isso seja útil para alguém que está por aí.
fonte
Procurando um bom tutorial para iniciantes sobre o assunto, encontrei o melhor tutorial aqui .
No
MIScrollView.h
exemplo na parte inferior do tutorial, certifique-se de colocar um espaço emcomo você vê.
fonte
Quando
UITextField
está em umaUITableViewCell
rolagem deve ser configurado automaticamente.Caso contrário, é provavelmente por causa do código / configuração incorretos da visualização da tabela.
Por exemplo, quando recarreguei minha mesa longa com uma
UITextField
na parte inferior, como a seguir,então meu campo de texto na parte inferior foi obscurecido pelo teclado que apareceu quando eu cliquei dentro do campo de texto.
Para consertar isso, eu tive que fazer isso -
fonte
viewWillAppear
não é chamado. EreloadData
não faz as linhas obscurecidas se tornarem visíveis.Use esse terceiro que você não precisa escrever nem uma linha
https://github.com/hackiftekhar/IQKeyboardManager
faça o download do projeto e arraste e solte
IQKeyboardManager
no seu projeto. Se você encontrar algum problema, leia oREADME
documento.Caras realmente é remover dor de cabeça para gerenciar o teclado.
fonte
Nota : esta resposta assume que seu campo de texto está em um scrollView.
Prefiro lidar com isso usando scrollContentInset e scrollContentOffset em vez de mexer nos quadros da minha exibição.
Primeiro, vamos ouvir as notificações do teclado
O próximo passo é manter uma propriedade que represente o primeiro atendedor atual (UITextfield / UITextVIew que atualmente possui o teclado).
Usamos os métodos delegados para definir essa propriedade. Se você estiver usando outro componente, precisará de algo semelhante.
Observe que, para o campo de texto, o definimos em didBeginEditing e para textView em shouldBeginEditing. Isso ocorre porque o textViewDidBeginEditing é chamado após UIKeyboardWillShowNotification por algum motivo.
Finalmente, aqui está a mágica
fonte
Esta é a solução usando o Swift.
fonte