Ich habe eine App, bei der ich im Interface Builder eine UIView
aufbaue, die ein Textfeld am unteren Rand der Ansicht hat. Wenn ich die App starte und versuche, Text in dieses Feld einzugeben, wird die Tastatur über das Feld hochgeschoben, sodass ich nicht sehen kann, was ich tippe, bis ich die Tastatur wieder verstecke.
Hat jemand anderes dieses Problem gefunden und einen guten Weg gefunden, um dieses Problem zu lösen, ohne die übergeordnete Ansicht scrollbar zu machen oder das Textfeld auf dem Bildschirm nach oben zu verschieben?
Die übliche Lösung besteht darin, das Feld (und alles darüber) mit einer Animation nach oben zu verschieben und dann wieder nach unten zu verschieben. Möglicherweise müssen Sie das Textfeld und einige der anderen Elemente in eine andere Ansicht einfügen und die Ansicht als Einheit verschieben. (Ich nenne diese Dinge "Platten" wie in "tektonischen Platten", aber das ist nur ich). Aber hier ist die allgemeine Idee, wenn Sie nicht schick sein müssen.
- (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];
}
Das hat Wunder gewirkt Schiebe-Uitextfelder
Insbesondere hat es den Vorteil, dass der Abstand der Folienanimation abhängig von der Position des Textfelds berechnet wird.
IQKeyboardManager Tun Sie dies für Sie mit NO LINE OF CODE. Sie müssen nur die zugehörige Quelldatei per Drag & Drop in das Projekt ziehen. IQKeyboardManager unterstützt auch Geräteorientierung, Automatische UIToolbar-Verwaltung, keyboardDistanceFromTextField und vieles mehr, als Sie denken.
Hier ist das Steuerungsflussdiagramm:
Schritt1: - Globale Benachrichtigungen von UITextField
, UITextView
und UIKeyboard
in einer Singleton-Klasse hinzugefügt. Ich habe es IQKeyboardManager genannt.
Schritt2: - Wenn Sie UIKeyboardWillShowNotification
-, UITextFieldTextDidBeginEditingNotification
- oder UITextViewTextDidBeginEditingNotification
-Benachrichtigungen gefunden haben, versuchen Sie, die topMostViewController
-Instanz aus der UIWindow.rootViewController
-Hierarchie abzurufen. Damit UITextField
UITextView
richtig aufgedeckt werden kann, muss der Frame von topMostViewController.view
angepasst werden.
_/Step3: - Berechnete erwartete Bewegungsentfernung von topMostViewController.view
in Bezug auf die erste Antwort UITextField
UITextView
.
_/Schritt4: - Verschiebt topMostViewController.view.frame
entsprechend der erwarteten Bewegungsentfernung nach oben/unten.
Schritt5: - Wenn eine Benachrichtigung über UIKeyboardWillHideNotification
, UITextFieldTextDidEndEditingNotification
oder UITextViewTextDidEndEditingNotification
gefunden wird, versuchen Sie erneut, die topMostViewController
-Instanz aus der UIWindow.rootViewController
-Hierarchie abzurufen.
Schritt6: - Berechnete gestörte Entfernung von topMostViewController.view
, die an ihrer ursprünglichen Position wiederhergestellt werden muss.
Step7: - Wiederhergestellt topMostViewController.view.frame
entsprechend der gestörten Entfernung.
Schritt8: - Instanziiertes Singleton IQKeyboardManager Klasseninstanz beim Laden der App, sodass sich UITextField
/UITextView
in der App automatisch an die erwartete Bewegungsentfernung anpassen.
Das ist alles
Um die Antwort von Amagrammer zu erweitern, finden Sie hier eine Beispielklasse:
LoginViewController.h
@interface LoginViewController : UIViewController <UITextFieldDelegate> {
}
@property (nonatomic, retain) IBOutlet UITextField *emailTextField;
@property (nonatomic, retain) IBOutlet UITextField *passwordTextField;
Beachten Sie, dass wir das "UITextFieldDelegate" implementieren.
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];
}
Wie wäre es mit der offiziellen Lösung: Bewegen von Inhalten, die sich unter der Tastatur befinden
Um Ihren Inhalt anzupassen, müssen Sie normalerweise die Größe eines oder .__ ändern. Weitere Ansichten und Positionieren, so dass das Textobjekt bleibt sichtbar. Die einfachste Möglichkeit, Textobjekte mit der Tastatur zu verwalten, ist um sie in ein UIScrollView-Objekt (oder eine seiner Unterklassen wie UITableView) einzubetten. Wenn die Tastatur angezeigt wird, müssen Sie alles tun setzt den Inhaltsbereich der Bildlaufansicht zurück und blättert das gewünschte Bild Textobjekt in Position. Also als Antwort auf eine UIKeyboardDidShowNotification, würde Ihre Handler-Methode die folgende:
- Holen Sie sich die Größe der Tastatur.
- Passen Sie den unteren Inhalt der Bildlaufansicht über die Tastatur an Höhe.
- Scrollen Sie das Zieltextfeld in die Ansicht.
// 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;
}
Ich habe das gleiche Problem in UITableView
textField-Zellen. Ich löse dieses Problem durch Implementieren der folgenden Methode zum Abhören der Tastaturbenachrichtigung.
Beobachter für die Benachrichtigungen hier:
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
Behandeln Sie diese Benachrichtigung mithilfe der folgenden Funktion:
(void)keyboardWasShown:(NSNotification*)aNotification
(void)keyboardWillBeHidden:(NSNotification*)aNotification
Sehen Sie sich das an ... __ Keine Mühe für Sie.
Diese Lösung ist sehr ordentlich. Alles, was Sie tun müssen, ist, Ihre Textfelder in ein UIScrollView
hinzuzufügen und die Klasse in TPKeyboardAvoidingScollView
zu ändern, wenn Sie Storyboards verwenden. Die Bildlaufansicht wird so erweitert, dass sie erkennt, wenn die Tastatur sichtbar ist, und sich in einem angemessenen Abstand über der Tastatur bewegt. Es ist die perfekte Lösung, weil es unabhängig von Ihrem _ UIViewController
ist. In der oben genannten Klasse wird alles Notwendige erledigt. Danke an Michael Tyson und allen.
Nachfolgend finden Sie eine schnelle Version von Amagrammers Antwort. Auch eine Variante mit dem UIKeyboardWillShowNotification -Ereignis, da ich die Größe der Tastaturen kennen musste, bevor die Ansicht verschoben wurde.
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)
}
Es gab eine großartige Lösung in Bearbeitung von Textfeldern, ohne zu verdecken (Link jetzt tot, hier ist ein Wayback-Link: https://web.archive.org/web/20091123074029/http://acts-as-geek. blogspot.com/2009/11/editing-textfields-without-obscuring.html ). Es zeigt, wie Sie eine vorhandene UIView
auf eine UIScrollView
verschieben und automatisch scrollen, wenn die Tastatur angezeigt wird.
Ich habe es ein wenig überarbeitet, um die korrekte Höhe für die UIScrollView
zu berechnen, wenn Steuerelemente (z. B. eine UITabBar
) unter der UIScrollBar
vorhanden sind. Siehe post Update uiview .
Hier ist eine Lösung mit Xcode5, iOS7:
Verwenden Sie die Blöcke UITextfieldDelegate und Animation.
Dies ist fast der gesamte Code für den ViewController, aber ich wollte den Delegiertencode für diejenigen hinzufügen, die mit dem Delegatenmuster (wie ich) noch etwas nicht vertraut sind. Ich habe auch Code zum Ausblenden der Tastatur hinzugefügt, wenn Sie von der Textansicht weg tippen.
Sie können die Ansichten (Schaltflächen, Textfelder usw.) so hoch verschieben, wie Sie möchten. Stellen Sie sicher, dass Sie sie wieder einsetzen (+100 und später -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];
}
Ich denke, eine Möglichkeit wäre, Ihre gesamte Ansichtsposition von (x, y) nach (x, y-keybaardHeight) zu verschieben, wenn das Textfeld angeklickt wird, und es zurückzusetzen, wenn die Tastatur nicht angezeigt wird. Dies könnte ein wenig merkwürdig erscheinen kommt auf (vielleicht wäre es nicht schlimm, wenn Sie es animieren).
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect frame=self.view.frame;
frame.Origin=CGPointMake(x...//set point here
self.view.frame=frame;
}
Wenn Sie cocos2d im Hochformatmodus verwenden, ändern Sie zusätzlich zu Amagrammers Lösung diese Zeile:
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
zu diesem:
[CCDirector sharedDirector].openGLView.frame = CGRectOffset([CCDirector sharedDirector].openGLView.frame, movement, 0);
Wenn Sie cocos2d im Querformat verwenden, nehmen Sie die obige Änderung vor und ändern Sie die up
-Werte in textFieldDidBeginEditing:
und textFieldDidEndEditing:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[self animateTextField:textField up:NO];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self animateTextField:textField up:YES];
}
https://github.com/ZulwiyozaPutra/Shift-Keyboard-Example Ich hoffe, diese Lösung hat geholfen. Sie sind alle Swift 3 geschrieben.
//
// 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)
}
}
Drag & Drop-Framework, das ich in meinen Projekten verwende. Unterstützt die automatische Entlassung, wenn Sie außerhalb des Ersthelfer tippen oder blättern.
Schieben Sie die Ansicht nach Bedarf auf und ab:
- (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);
}];
}
Vergessen Sie nicht, self
als UITextFieldDelegate
und als aktuelles textField delegate
zu setzen.
(Dank an Ammagrammer, dies ist nur eine kürzere Antwort mit Blöcken für Animationen.)
Ich glaube, bei neueren Versionen von iOS (6.1+, möglicherweise sogar früher) wird die zugrunde liegende Ansicht, zumindest für UITableView, automatisch verkleinert, wenn die Tastatur erscheint. Sie müssen also nur das Textfeld in dieser Ansicht sichtbar machen. In init
:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
dann:
- (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];
}
Ich hatte das gleiche Problem und fand, dass GTKeyboardHelper ein einfacher Ausweg ist.
Fügen Sie nach dem Ziehen und Ablegen des Frameworks in Ihrem Projekt die Header-Datei ein. __ Laden Sie das Beispielprojekt herunter, öffnen Sie es, und ziehen Sie das Objekt "Keyboard Helper" aus dem Objektabschnitt in der Xib-Datei in den Objektabschnitt im Interface-Builder Ihres Projekts.
Ziehen Sie alle Ihre Ansichten und lassen Sie sie als "Kinder" des "Keyboard Helper" ablegen.
Ich habe noch etwas, wenn du willst. Der Punkt hier ist, dass Sie die Mitte Ihrer UIView für das Textfeld festlegen möchten, das Sie bearbeiten.
Zuvor müssen Sie Ihr INITIAL_CENTER als CGPoint von self.view.center und Ihr INITIAL_VIEW als CGRect speichern. von self.view.frame in einer const-Eigenschaft.
Sie können eine Methode wie folgt erstellen:
- (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];
}
Dann müssen Sie auf Ihrem UITextFieldDelegatecenterOn: (CGRect) mit folgenden Methoden aufrufen:
textFieldDidBeginEditing: (UITextField *)} _ als Parameter den Rahmen des Textfelds, auf das Sie zentrieren möchten.
Und Sie müssen es in Ihrem Event-Handler aufrufen, wo Sie Ihre Tastatur schließen,
textFieldDidEndEditing: (UITextField *)} kann eine der Möglichkeiten sein, den INITIAL_VIEW als Parameter von centerOn: (CGRect) zu setzen.
Bitte schau dir meinen Kommentar dazu an:
Wie gehen Sie mit der Situation um, in der sich die Tastatur befindet und der Rahmen mit Animation verkleinert und gescrollt wurde, sodass das Textfeld nicht abgedeckt wird. Wenn ich ein anderes Textfeld auswähle (das erste Textfeld noch bearbeitet), kann ich die Animation nicht noch einmal abspielen blättern Sie ggf. ein wenig weiter? Das Problem ist die Wiedergabe der gesamten Animation, wenn dies nicht erforderlich ist. Vielen Dank