Mit dem iOS SDK:
Ich habe eine UIView
mit UITextField
s, die eine Tastatur aufruft. Ich brauche es, um:
Lassen Sie den Inhalt der UIScrollView
scrollen, um die anderen Textfelder anzuzeigen, sobald die Tastatur aufgerufen wird
Automatisch "springen" (durch Aufwärtsblättern) oder Verkürzen
Ich weiß, dass ich eine UIScrollView
brauche. Ich habe versucht, die Klasse meiner UIView
in eine UIScrollView
zu ändern, aber ich kann die Textfelder immer noch nicht nach oben oder unten scrollen.
Benötige ich eine UIView
und eine UIScrollView
? Geht einer in den anderen?
Was muss implementiert werden, um automatisch zum aktiven Textfeld zu blättern?
Im Idealfall wird so viel der Einrichtung der Komponenten wie möglich im Interface Builder vorgenommen. Ich möchte nur Code schreiben, was es braucht.
Hinweis: Die UIView
(oder UIScrollView
), mit der ich arbeite, wird von einer Tab-Leiste (UITabBar
) aufgerufen, die normal funktionieren muss.
Bearbeiten: Ich füge die Bildlaufleiste nur für die Tastatur hinzu. Auch wenn dies nicht erforderlich ist, bietet es mir eine bessere Benutzeroberfläche, da der Benutzer beispielsweise scrollen und Textfelder ändern kann.
Ich habe es funktioniert, wo ich die Framegröße der UIScrollView
ändere, wenn die Tastatur hoch und runter geht. Ich verwende einfach:
-(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
}
Dies bewegt sich jedoch nicht automatisch "nach oben" oder zentriert die unteren Textfelder im sichtbaren Bereich, was ich wirklich gerne hätte.
Sie benötigen ein ScrollView
nur, wenn die Inhalte, die Sie jetzt haben, nicht in den iPhone-Bildschirm passen (Wenn Sie ScrollView
als Übersicht der Komponenten hinzufügen. Nur um das TextField
-Fenster aufzurufen, wenn die Tastatur hochgefahren wird, dann es wird nicht benötigt.)
Um textfields
anzuzeigen, ohne von der Tastatur ausgeblendet zu werden, wird standardmäßig die Ansicht mit Textfeldern nach oben/unten verschoben, wenn die Tastatur angezeigt wird.
Hier ist ein Beispielcode:
#define kOFFSET_FOR_KEYBOARD 80.0
-(void)keyboardWillShow {
// Animate the current view out of the way
if (self.view.frame.Origin.y >= 0)
{
[self setViewMovedUp:YES];
}
else if (self.view.frame.Origin.y < 0)
{
[self setViewMovedUp:NO];
}
}
-(void)keyboardWillHide {
if (self.view.frame.Origin.y >= 0)
{
[self setViewMovedUp:YES];
}
else if (self.view.frame.Origin.y < 0)
{
[self setViewMovedUp:NO];
}
}
-(void)textFieldDidBeginEditing:(UITextField *)sender
{
if ([sender isEqual:mailTf])
{
//move the main view, so that the keyboard does not hide it.
if (self.view.frame.Origin.y >= 0)
{
[self setViewMovedUp:YES];
}
}
}
//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3]; // if you want to slide up the view
CGRect rect = self.view.frame;
if (movedUp)
{
// 1. move the view's Origin up so that the text field that will be hidden come above the keyboard
// 2. increase the size of the view so that the area behind the keyboard is covered up.
rect.Origin.y -= kOFFSET_FOR_KEYBOARD;
rect.size.height += kOFFSET_FOR_KEYBOARD;
}
else
{
// revert back to the normal state.
rect.Origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
self.view.frame = rect;
[UIView commitAnimations];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
Ich hatte auch eine Menge Probleme mit einem UIScrollView
, das aus mehreren UITextFields
bestand, von denen einer oder mehrere von ihnen beim Editieren durch die Tastatur verdeckt würden.
Folgendes sollten Sie beachten, wenn Ihr UIScrollView
nicht ordnungsgemäß gescrollt wird.
1) Stellen Sie sicher, dass Ihre contentSize die Rahmengröße UIScrollView
überschreitet. Um UIScrollViews
zu verstehen, ist es so, dass UIScrollView
wie ein Anzeigefenster für den in contentSize definierten Inhalt ist. Wenn also UIScrollview
irgendwo scrollen darf, muss contentSize größer als UIScrollView
sein. Andernfalls ist kein Bildlauf erforderlich, da alles, was in contentSize definiert ist, bereits sichtbar ist. BTW, Standardinhalt contentSize = CGSizeZero
.
2) Nachdem Sie nun verstanden haben, dass UIScrollView
wirklich ein Fenster in Ihren "Inhalt" ist, besteht der Weg, um sicherzustellen, dass die Tastatur Ihr UIScrollView's
-Anzeige "Fenster" nicht verdeckt, darin, die Größe von UIScrollView
zu ändern Wenn die Tastatur vorhanden ist, haben Sie das Fenster UIScrollView
, das nur der ursprünglichen UIScrollView
frame.size.höhe minus der Höhe der Tastatur entspricht. Dadurch wird sichergestellt, dass Ihr Fenster nur aus diesem kleinen sichtbaren Bereich besteht.
3) Hier ist der Haken: Als ich das zum ersten Mal implementierte, dachte ich, ich müsste CGRect
des bearbeiteten Textfelds bekommen und die UIScrollView's
scrollRecToVisible-Methode aufrufen. Ich habe die UITextFieldDelegate
Methode textFieldDidBeginEditing
mit dem Aufruf der scrollRecToVisible
Methode implementiert. Dies funktionierte tatsächlich mit einem seltsamen Nebeneffekt, dass das Scrollen Einrasten der UITextField
in Position wäre. Die längste Zeit konnte ich nicht herausfinden, was es war. Dann habe ich die textFieldDidBeginEditing
Delegate-Methode auskommentiert und es funktioniert alles !! (???). Wie sich herausgestellt hat, bringt der UIScrollView
tatsächlich den aktuell bearbeiteten UITextField
implizit in das sichtbare Fenster. Meine Implementierung der Methode UITextFieldDelegate
und der darauffolgende Aufruf von scrollRecToVisible
waren überflüssig und verursachten die seltsame Nebenwirkung.
Hier sind die Schritte, um Ihr UITextField
in einem UIScrollView
richtig in die richtige Position zu rollen, wenn die Tastatur angezeigt wird.
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:self.view.window];
keyboardIsShown = NO;
//make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
CGSize scrollContentSize = CGSizeMake(320, 345);
self.scrollView.contentSize = scrollContentSize;
}
- (void)keyboardWillHide:(NSNotification *)n
{
NSDictionary* userInfo = [n userInfo];
// get the size of the keyboard
CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
// resize the scrollview
CGRect viewFrame = self.scrollView.frame;
// I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
viewFrame.size.height += (keyboardSize.height - kTabBarHeight);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[self.scrollView setFrame:viewFrame];
[UIView commitAnimations];
keyboardIsShown = NO;
}
- (void)keyboardWillShow:(NSNotification *)n
{
// This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown. This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`. If we were to resize the `UIScrollView` again, it would be disastrous. NOTE: The keyboard notification will fire even when the keyboard is already shown.
if (keyboardIsShown) {
return;
}
NSDictionary* userInfo = [n userInfo];
// get the size of the keyboard
CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
// resize the noteView
CGRect viewFrame = self.scrollView.frame;
// I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[self.scrollView setFrame:viewFrame];
[UIView commitAnimations];
keyboardIsShown = YES;
}
viewDidLoad
viewDidUnload
auf.contentSize
eingestellt ist und größer als Ihr UIScrollView
bei viewDidLoad
ist.UIScrollView
, wenn die Tastatur vorhanden istUIScrollView
, wenn die Tastatur wegfällt.UITextField
-Tabulator aktiviert wird, auch wenn die Tastatur bereits vorhanden ist, um Verkleinern der UIScrollView
wenn es schon geschrumpft istZu beachten ist, dass UIKeyboardWillShowNotification
auch dann ausgelöst wird, wenn die Tastatur bereits auf dem Bildschirm angezeigt wird, wenn Sie auf ein anderes UITextField
tippen. Ich habe mich darum gekümmert, indem ich ein ivar verwendet habe, um zu verhindern, dass UIScrollView
geändert wird, wenn die Tastatur bereits auf dem Bildschirm angezeigt wird. Das unbeabsichtigte Ändern der Größe von UIScrollView
, wenn sich die Tastatur bereits dort befindet, wäre verheerend!
Ich hoffe, dieser Code erspart einigen von Ihnen Kopfschmerzen.
Es ist eigentlich am besten, nur die Implementierung von Apple zu verwenden, wie in den docs beschrieben. Der von ihnen bereitgestellte Code ist jedoch fehlerhaft. Ersetzen Sie den in keyboardWasShown:
direkt unter den Kommentaren gefundenen Abschnitt durch Folgendes:
NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);
CGPoint Origin = activeRect.Origin;
Origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, Origin)) {
CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
[backScrollView setContentOffset:scrollPoint animated:YES];
}
Die Probleme mit Apples Code lauten wie folgt: (1) Sie berechnen immer, ob sich der Punkt innerhalb des Rahmens der Ansicht befindet, es handelt sich jedoch um eine ScrollView
, sodass der Bildlauf möglicherweise bereits gescrollt wurde und Sie diesen Versatz berücksichtigen müssen:
Origin.y -= scrollView.contentOffset.y
(2) Sie verschieben das contentOffset um die Höhe der Tastatur, aber wir möchten das Gegenteil (wir möchten die contentOffset
um die auf dem Bildschirm sichtbare Höhe verschieben, nicht die, was nicht ist):
activeField.frame.Origin.y-(aRect.size.height)
Rufen Sie in textFieldDidBeginEditting
und in textFieldDidEndEditing
die Funktion [self animateTextField:textField up:YES]
so auf:
-(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 = -130; // Tweak as needed
const float movementDuration = 0.3f; // Tweak as needed
int movement = (up ? movementDistance : -movementDistance);
[UIView beginAnimations: @"animateTextField" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
Ich hoffe, dieser Code wird Ihnen helfen.
In Swift 2
func animateTextField(textField: UITextField, up: Bool)
{
let movementDistance:CGFloat = -130
let movementDuration: Double = 0.3
var movement:CGFloat = 0
if up
{
movement = movementDistance
}
else
{
movement = -movementDistance
}
UIView.beginAnimations("animateTextField", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration)
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
UIView.commitAnimations()
}
func textFieldDidBeginEditing(textField: UITextField)
{
self.animateTextField(textField, up:true)
}
func textFieldDidEndEditing(textField: UITextField)
{
self.animateTextField(textField, up:false)
}
Swift 3
func animateTextField(textField: UITextField, up: Bool)
{
let movementDistance:CGFloat = -130
let movementDuration: Double = 0.3
var movement:CGFloat = 0
if up
{
movement = movementDistance
}
else
{
movement = -movementDistance
}
UIView.beginAnimations("animateTextField", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration)
self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
UIView.commitAnimations()
}
func textFieldDidBeginEditing(textField: UITextField)
{
self.animateTextField(textField: textField, up:true)
}
func textFieldDidEndEditing(textField: UITextField)
{
self.animateTextField(textField: textField, up:false)
}
Nur TextFields verwenden:
1a) Verwenden von Interface Builder
: Wählen Sie Alle TextFields => Bearbeiten => Einbetten in => ScrollView
1b) Manuelles Einbetten von TextFields in UIScrollView mit dem Namen scrollView
2) Setze UITextFieldDelegate
3) Setzen Sie jeden textField.delegate = self;
(oder stellen Sie Verbindungen in Interface Builder
her)
4) Kopieren/Einfügen:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
CGPoint scrollPoint = CGPointMake(0, textField.frame.Origin.y);
[scrollView setContentOffset:scrollPoint animated:YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
[scrollView setContentOffset:CGPointZero animated:YES];
}
Für Universal Solution war mein Ansatz für die Implementierung von IQKeyboardManager .
Schritt1: - Ich habe globale Benachrichtigungen von UITextField
, UITextView
und UIKeyboard
in einer Singleton-Klasse hinzugefügt. Ich nenne es IQKeyboardManager .
Schritt2: - Wenn ich UIKeyboardWillShowNotification
-, UITextFieldTextDidBeginEditingNotification
- oder UITextViewTextDidBeginEditingNotification
-Benachrichtigungen gefunden habe, versuche ich, die topMostViewController
-Instanz aus der UIWindow.rootViewController
-Hierarchie abzurufen. Damit UITextField
UITextView
richtig aufgedeckt werden kann, muss der Frame von topMostViewController.view
angepasst werden.
_/Schritt3: - Ich habe die erwartete Bewegungsentfernung von topMostViewController.view
in Bezug auf die zuerst angesprochene UITextField
UITextView
berechnet.
_/Schritt4: - Ich habe den topMostViewController.view.frame
entsprechend der erwarteten Bewegungsentfernung nach oben/unten verschoben.
Schritt5: - Wenn ich UIKeyboardWillHideNotification
-, UITextFieldTextDidEndEditingNotification
- oder UITextViewTextDidEndEditingNotification
-Benachrichtigung gefunden habe, versuche ich erneut, die topMostViewController
-Instanz aus der UIWindow.rootViewController
-Hierarchie abzurufen.
Schritt6: - Ich habe den gestörten Abstand von topMostViewController.view
berechnet, der an seiner ursprünglichen Position wiederhergestellt werden muss.
Step7: - Ich habe topMostViewController.view.frame
entsprechend der gestörten Entfernung restauriert.
Step8: - Ich instanziierte das Singleton IQKeyboardManager -Klasseninstanz beim Laden der App, so dass sich jeder UITextField
UITextView
in der App automatisch an die erwartete Bewegungsentfernung anpassen.
Das ist alles IQKeyboardManager erledigt für Sie mit _/NO LINE OF CODE wirklich !! Sie müssen nur die zugehörige Quelldatei per Drag & Drop in das Projekt einfügen. IQKeyboardManager unterstützt auch Geräteorientierung, Automatic UIToolbar Management, KeybkeyboardDistanceFromTextField und vieles mehr, als Sie denken.
Ich habe eine universelle Drop-In-Klasse UIScrollView
, UITableView
und sogar UICollectionView
zusammengestellt, die dafür sorgt, dass alle Textfelder innerhalb der Tastatur aus der Tastatur verschoben werden.
Wenn die Tastatur erscheint, sucht die Unterklasse die zu bearbeitende Unteransicht und passt ihren Frame- und Inhalt-Versatz an, um sicherzustellen, dass die Ansicht sichtbar ist, wobei die Animation dem Popup der Tastatur entspricht. Wenn die Tastatur ausgeblendet wird, wird die vorherige Größe wiederhergestellt.
Es sollte grundsätzlich mit jedem Setup funktionieren, entweder mit einer UITableView
-basierten Schnittstelle oder mit Ansichten, die manuell platziert wurden.
Hier ist tis: Lösung zum Verschieben von Textfeldern aus der Tastatur
Für SwiftProgrammierer:
Dies erledigt alles für Sie, fügen Sie diese einfach in Ihre View-Controller-Klasse ein, implementieren Sie die UITextFieldDelegate
in Ihren View-Controller und setzen Sie den Delegaten von textField auf self
.
textField.delegate = self // Setting delegate of your UITextField to self
Implementieren Sie die Delegate-Callback-Methoden:
func textFieldDidBeginEditing(textField: UITextField) {
animateViewMoving(true, moveValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
animateViewMoving(false, moveValue: 100)
}
// Lifting the view up
func animateViewMoving (up:Bool, moveValue :CGFloat){
let movementDuration:NSTimeInterval = 0.3
let movement:CGFloat = ( up ? -moveValue : moveValue)
UIView.beginAnimations( "animateView", context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(movementDuration )
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
UIView.commitAnimations()
}
Es gibt bereits viele Antworten, aber dennoch hatte keine der oben genannten Lösungen alles, was man für eine "perfekte" fehlerfreie, abwärtskompatible und flimmerfreie Animation benötigt. (Fehler beim Animieren von Frames/Begrenzungen und contentOffset zusammen, unterschiedliche Oberflächenausrichtungen, iPad-Split-Tastatur, ...)
Lassen Sie mich meine Lösung teilen:
(vorausgesetzt, Sie haben UIKeyboardWill(Show|Hide)Notification
eingerichtet)
// Called when UIKeyboardWillShowNotification is sent
- (void)keyboardWillShow:(NSNotification*)notification
{
// if we have no view or are not visible in any window, we don't care
if (!self.isViewLoaded || !self.view.window) {
return;
}
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardFrameInWindow;
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];
// the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil];
CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView);
UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);
// this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
_scrollView.contentInset = newContentInsets;
_scrollView.scrollIndicatorInsets = newContentInsets;
/*
* Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element
* that should be visible, e.g. a purchase button below an amount text field
* it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
*/
if (_focusedControl) {
CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any Nice visual offset between control and keyboard or control and top of the scroll view.
CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.Origin.y - _scrollView.contentOffset.y;
CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;
// this is the visible part of the scroll view that is not hidden by the keyboard
CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;
if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
// scroll up until the control is in place
CGPoint newContentOffset = _scrollView.contentOffset;
newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);
// make sure we don't set an impossible offset caused by the "Nice visual offset"
// if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight);
[_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
} else if (controlFrameInScrollView.Origin.y < _scrollView.contentOffset.y) {
// if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
CGPoint newContentOffset = _scrollView.contentOffset;
newContentOffset.y = controlFrameInScrollView.Origin.y;
[_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
}
}
[UIView commitAnimations];
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillHide:(NSNotification*)notification
{
// if we have no view or are not visible in any window, we don't care
if (!self.isViewLoaded || !self.view.window) {
return;
}
NSDictionary *userInfo = notification.userInfo;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
// undo all that keyboardWillShow-magic
// the scroll view will adjust its contentOffset apropriately
_scrollView.contentInset = UIEdgeInsetsZero;
_scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
[UIView commitAnimations];
}
Shiun sagte: "Wie sich herausstellte, bringt das UIScrollView tatsächlich das aktuell bearbeitete UITextField implizit in das sichtbare Fenster." Dies scheint für iOS 3.1.3 der Fall zu sein, nicht jedoch für 3.2, 4.0 oder 4.1. Ich musste ein explizites scrollRectToVisible hinzufügen, um das UITextField auf iOS> = 3.2 sichtbar zu machen.
Eine Sache, die Sie berücksichtigen sollten, ist, ob Sie eine UITextField
alleine verwenden möchten. Ich habe keine gut konzipierten iPhone-Apps gefunden, die UITextFields
außerhalb von UITableViewCells
verwenden.
Es ist etwas mehr Arbeit, aber ich empfehle Ihnen, alle Dateneingabesichten und Tabellensichten zu implementieren. Fügen Sie Ihrer UITextView
eine UITableViewCells
hinzu.
Dieses Dokument enthält eine Lösung für dieses Problem. Sehen Sie sich den Quellcode unter "Verschieben von Inhalten unter der Tastatur" an. Das ist ziemlich einfach.
BEARBEITEN: Es wurde eine kleine Störung im Beispiel bemerkt. Wahrscheinlich möchten Sie auf UIKeyboardWillHideNotification
statt auf UIKeyboardDidHideNotification
achten. Andernfalls wird die Bildlaufansicht hinter der Tastatur für die Dauer der Animation zum Schließen der Tastatur abgeschnitten.
Einfachste Lösung gefunden
- (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];
}
Kleine Korrektur, die für viele UITextFields funktioniert
#pragma mark UIKeyboard handling
#define kMin 150
-(void)textFieldDidBeginEditing:(UITextField *)sender
{
if (currTextField) {
[currTextField release];
}
currTextField = [sender retain];
//move the main view, so that the keyboard does not hide it.
if (self.view.frame.Origin.y + currTextField.frame.Origin. y >= kMin) {
[self setViewMovedUp:YES];
}
}
//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3]; // if you want to slide up the view
CGRect rect = self.view.frame;
if (movedUp)
{
// 1. move the view's Origin up so that the text field that will be hidden come above the keyboard
// 2. increase the size of the view so that the area behind the keyboard is covered up.
rect.Origin.y = kMin - currTextField.frame.Origin.y ;
}
else
{
// revert back to the normal state.
rect.Origin.y = 0;
}
self.view.frame = rect;
[UIView commitAnimations];
}
- (void)keyboardWillShow:(NSNotification *)notif
{
//keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately
if ([currTextField isFirstResponder] && currTextField.frame.Origin.y + self.view.frame.Origin.y >= kMin)
{
[self setViewMovedUp:YES];
}
else if (![currTextField isFirstResponder] && currTextField.frame.Origin.y + self.view.frame.Origin.y < kMin)
{
[self setViewMovedUp:NO];
}
}
- (void)keyboardWillHide:(NSNotification *)notif
{
//keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately
if (self.view.frame.Origin.y < 0 ) {
[self setViewMovedUp:NO];
}
}
- (void)viewWillAppear:(BOOL)animated
{
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification object:self.view.window];
}
- (void)viewWillDisappear:(BOOL)animated
{
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}
Der RPDP-Code verschiebt das Textfeld erfolgreich von der Tastatur. Wenn Sie jedoch nach dem Scrollen nach oben und nach oben blättern, wurde der obere Bereich aus der Ansicht verschoben. Dies gilt für den Simulator und das Gerät. Um den Inhalt oben in dieser Ansicht zu lesen, muss die Ansicht neu geladen werden.
Soll der folgende Code nicht die Sicht nach unten bringen?
else
{
// revert back to the normal state.
rect.Origin.y += kOFFSET_FOR_KEYBOARD;
rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
Ich bin nicht sicher, ob die Ansicht nach oben zu verschieben, der richtige Ansatz ist. Ich habe es auf eine andere Weise gemacht, indem ich die Größe der UIScrollView geändert habe. Ich habe es auf einem kleinen Artikel ausführlich erklärt.
Um zum ursprünglichen Ansichtszustand zurückzukehren, fügen Sie Folgendes hinzu:
-(void)textFieldDidEndEditing:(UITextField *)sender
{
//move the main view, so that the keyboard does not hide it.
if (self.view.frame.Origin.y < 0)
{
[self setViewMovedUp:NO];
}
}
Es gibt so viele Lösungen, aber ich habe einige Stunden damit verbracht, bis es funktioniert. Also habe ich diesen Code hier eingefügt (einfach in das Projekt einfügen, Änderungen müssen nicht vorgenommen werden):
@interface RegistrationViewController : UIViewController <UITextFieldDelegate>{
UITextField* activeField;
UIScrollView *scrollView;
}
@end
- (void)viewDidLoad
{
[super viewDidLoad];
scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
//scrool view must be under main view - swap it
UIView* natView = self.view;
[self setView:scrollView];
[self.view addSubview:natView];
CGSize scrollViewContentSize = self.view.frame.size;
[scrollView setContentSize:scrollViewContentSize];
[self registerForKeyboardNotifications];
}
- (void)viewDidUnload {
activeField = nil;
scrollView = nil;
[self unregisterForKeyboardNotifications];
[super viewDidUnload];
}
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShown:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
-(void)unregisterForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)keyboardWillShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect frame = self.view.frame;
frame.size.height -= kbSize.height;
CGPoint fOrigin = activeField.frame.Origin;
fOrigin.y -= scrollView.contentOffset.y;
fOrigin.y += activeField.frame.size.height;
if (!CGRectContainsPoint(frame, fOrigin) ) {
CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.Origin.y + activeField.frame.size.height - frame.size.height);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
[scrollView setContentOffset:CGPointZero animated:YES];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
P .: Ich hoffe, der Code hilft jemandem, schnell den gewünschten Effekt zu erzielen. (Xcode 4.5)
@ user271753
Um Ihre Ansicht wieder auf das Original zu bringen, fügen Sie Folgendes hinzu:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
[self setViewMovedUp:NO];
return YES;
}
Versuchen Sie diesen kurzen Trick.
- (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 = textField.frame.Origin.y / 2; // 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];
}
Es ist keine Bildlaufansicht erforderlich, um den Ansichtsrahmen verschieben zu können. Sie können den Rahmen einer viewcontroller's
-Ansicht ändern, sodass die gesamte Ansicht gerade so weit nach oben verschoben wird, dass das erste Antwortfeld über der Tastatur angezeigt wird. Als ich auf dieses Problem stieß, habe ich eine Unterklasse von UIViewController
erstellt, die dies tut. Es wird darauf hingewiesen, dass auf der Tastatur eine Benachrichtigung angezeigt wird, und die Unteransicht des ersten Antworters wird angezeigt (und, falls erforderlich), wird die Hauptansicht gerade nach oben bewegt, sodass sich der erste Antwortende über der Tastatur befindet. Wenn die Tastatur ausgeblendet wird, wird die Ansicht dahin animiert, wo sie sich befand.
Um diese Unterklasse zu verwenden, machen Sie aus Ihrem benutzerdefinierten View-Controller eine Unterklasse von GMKeyboardVC und erbt diese Funktion (stellen Sie sicher, dass Sie viewWillAppear
und viewWillDisappear
implementieren, die sie super aufrufen müssen). Die Klasse ist auf github .
Gemäß the docs (ab iOS 3.0) ändert die UITableViewController
-Klasse automatisch ihre Tabellensicht, wenn Textfelder inline bearbeitet werden. Ich denke, es reicht nicht aus, das Textfeld in eine UITableViewCell
zu setzen, wie einige angegeben haben.
Von den Dokumenten :
Ein Table-View-Controller unterstützt die Inline-Bearbeitung von Table-View-Zeilen; Wenn z. B. Zeilen im Bearbeitungsmodus eingebettete Textfelder enthalten, wird es scrollt die Zeile, die gerade bearbeitet wird, über der virtuellen Tastatur, die .__ ist. angezeigt.
Hier ist die Hack-Lösung, die ich für ein bestimmtes Layout gefunden habe. Diese Lösung ähnelt der Matt-Gallagher-Lösung, indem ein Abschnitt in die Ansicht gerollt wird. Ich bin immer noch neu in der iPhone-Entwicklung und weiß nicht, wie die Layouts funktionieren. Also dieser Hack.
Meine Implementierung musste Scrollen unterstützen, wenn Sie in ein Feld klicken, und auch scrollen, wenn der Benutzer als Nächstes auf der Tastatur auswählt.
Ich hatte eine UIView mit einer Höhe von 775. Die Bedienelemente sind im Wesentlichen in 3er-Gruppen über einen großen Raum verteilt. Ich habe das folgende IB-Layout erhalten.
UIView -> UIScrollView -> [UI Components]
Hier kommt der Hack
Ich habe die UIScrollView-Höhe auf 500 Einheiten größer als das tatsächliche Layout (1250) eingestellt. Ich habe dann ein Array mit den absoluten Positionen erstellt, zu denen ich scrollen muss, und einer einfachen Funktion, um sie basierend auf der IB-Tag-Nummer zu erhalten.
static NSInteger stepRange[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 410
};
NSInteger getScrollPos(NSInteger i) {
if (i < TXT_FIELD_INDEX_MIN || i > TXT_FIELD_INDEX_MAX) {
return 0 ;
return stepRange[i] ;
}
Jetzt müssen Sie nur noch die folgenden beiden Codezeilen in textFieldDidBeginEditing und textFieldShouldReturn verwenden (letzteres, wenn Sie eine nächste Feldnavigation erstellen).
CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
[self.scrollView setContentOffset:point animated:YES] ;
Ein Beispiel.
- (void) textFieldDidBeginEditing:(UITextField *)textField
{
CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
[self.scrollView setContentOffset:point animated:YES] ;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSInteger nextTag = textField.tag + 1;
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
[nextResponder becomeFirstResponder];
CGPoint point = CGPointMake(0, getScrollPos(nextTag)) ;
[self.scrollView setContentOffset:point animated:YES] ;
}
else{
[textField resignFirstResponder];
}
return YES ;
}
Diese Methode "rollt" nicht wie andere Methoden zurück. Dies war keine Voraussetzung. Dies war wieder eine ziemlich "große" UIView, und ich hatte keine Tage Zeit, um die internen Layout-Engines zu lernen.
Hier Ich habe die einfachste Lösung für den Umgang mit der Tastatur gefunden.
Sie müssen lediglich Beispielcode kopieren und einfügen und Ihr Textfeld oder die Ansicht ändern, die Sie nach oben verschieben möchten.
Schritt 1
Kopieren Sie einfach zwei Methoden in Ihren Controller
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (void)deregisterFromKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
Schritt 2
registrieren und Abmelden der Tastaturbenachrichtigungen in viewWillAppear und viewWillDisappear -Methoden.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self registerForKeyboardNotifications];
}
- (void)viewWillDisappear:(BOOL)animated
{
[self deregisterFromKeyboardNotifications];
[super viewWillDisappear:animated];
}
Schritt 3
Hier kommt der Soul-Teil. Ersetzen Sie einfach Ihr Textfeld und ändern Sie Höhe, wie viel Sie nach oben bewegen möchten.
- (void)keyboardWasShown:(NSNotification *)notification
{
NSDictionary* info = [notification userInfo];
CGSize currentKeyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
//you need replace your textfield instance here
CGPoint textFieldOrigin = self.tokenForPlaceField.frame.Origin;
CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height;
CGRect visibleRect = self.view.frame;
visibleRect.size.height -= currentKeyboardSize.height;
if (!CGRectContainsPoint(visibleRect, textFieldOrigin))
{
//you can add yor desired height how much you want move keypad up, by replacing "textFieldHeight" below
CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height
[self.scrollView setContentOffset:scrollPoint animated:YES];
}
}
- (void)keyboardWillBeHidden:(NSNotification *)notification
{
[self.scrollView setContentOffset:CGPointZero animated:YES];
}
Referenz: Na ja, Bitte schätzen Sie diesen Kerl , der diesen schönen Code-Snip geteilt hat, saubere Lösung.
Hoffe, das wäre sicherlich hilfreich für jemanden da draußen.
Swift 4.
Sie können problemlos UITextField
oder UIView
mit UIKeyBoard
mit Animation
auf und ab bewegen
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var textField: UITextField!
@IBOutlet var chatView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
textField.resignFirstResponder()
}
@objc func keyboardWillChange(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
let deltaY = targetFrame.Origin.y - curFrame.Origin.y
print("deltaY",deltaY)
UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
self.chatView.frame.Origin.y+=deltaY // Here You Can Change UIView To UITextField
},completion: nil)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
Auf der Suche nach einem guten Tutorial für Anfänger zu diesem Thema, fand das beste Tutorial hier .
Stellen Sie im MIScrollView.h
-Beispiel am Ende des Tutorials sicher, dass Sie ein Leerzeichen in setzen
@property (nonatomic, retain) id backgroundTapDelegate;
wie du siehst.
Wenn sich UITextField
in einer UITableViewCell
befindet, sollte das Scrollen automatisch eingerichtet werden.
Wenn dies nicht der Fall ist, liegt dies wahrscheinlich an einem falschen Code/Setup der Tabellenansicht.
Zum Beispiel, wenn ich meine lange Tabelle mit einer UITextField
am unteren Ende wie folgt neu geladen habe,
-(void) viewWillAppear:(BOOL)animated
{
[self.tableview reloadData];
}
dann wurde mein Textfeld am unteren Rand von der Tastatur verdeckt, die angezeigt wurde, als ich in das Textfeld klickte.
Um das zu beheben, musste ich das tun -
-(void) viewWillAppear:(BOOL)animated
{
//add the following line to fix issue
[super viewWillAppear:animated];
[self.tableview reloadData];
}
Mit diesem Drittanbieter brauchen Sie nicht einmal eine Zeile zu schreiben
https://github.com/hackiftekhar/IQKeyboardManager
laden Sie das Projekt herunter und ziehen Sie den IQKeyboardManager per Drag & Drop in Ihr Projekt. Wenn Sie ein Problem finden, lesen Sie bitte README document.
Jungs wirklich seine Kopfschmerzen zu entfernen, um die Tastatur zu verwalten ..
Danke und viel Glück!
Hinweis : Diese Antwort setzt voraus, dass sich Ihr textField in einem scrollView befindet.
Ich gehe lieber damit um, indem ich scrollContentInset und scrollContentOffset benutze, anstatt mit den Frames meiner Ansicht zu verwechseln.
Lassen Sie uns zunächst die Tastaturbenachrichtigungen abhören
//call this from viewWillAppear
-(void)addKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
//call this from viewWillDisappear
-(void)removeKeyboardNotifications{
[[NSNotificationCenter default
Center] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
Der nächste Schritt besteht darin, eine Eigenschaft beizubehalten, die den aktuellen ersten Responder darstellt (UITextfield/UITextVIew, der aktuell die Tastatur besitzt).
Wir setzen die Delegatmethoden, um diese Eigenschaft festzulegen. Wenn Sie eine andere Komponente verwenden, benötigen Sie etwas Ähnliches.
Beachten Sie, dass wir für textfield es in didBeginEditing und für textView in shouldBeginEditing setzen. Dies liegt daran, dass textViewDidBeginEditing aus irgendeinem Grund nach UIKeyboardWillShowNotification aufgerufen wird.
-(BOOL)textViewShouldBeginEditing:(UITextView * )textView{
self.currentFirstResponder = textView;
return YES;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField{
self.currentFirstResponder = textField;
}
Schließlich ist hier die Magie
- (void)keyboardWillShow:(NSNotification*)aNotification{
NSDictionary* info = [aNotification userInfo];
CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
/*if currentFirstResponder is overlayed by the keyboard, move it so it bottom ends where the keyboard begins*/
if(self.currentFirstResponder){
//keyboard Origin in currentFirstResponderFrame
CGPoint keyboardOrigin = [self.currentFirstResponder convertPoint:kbFrame.Origin fromView:nil];
float spaceBetweenFirstResponderAndKeyboard = abs(self.currentFirstResponder.frame.size.height-keyboardOrigin.y);
//only scroll the scrollview if keyboard overlays the first responder
if(spaceBetweenFirstResponderAndKeyboard>0){
//if i call setContentOffset:animate:YES it behaves differently, not sure why
[UIView animateWithDuration:0.25 animations:^{
[self.scrollView setContentOffset:CGPointMake(0,self.scrollView.contentOffset.y+spaceBetweenFirstResponderAndKeyboard)];
}];
}
}
//set bottom inset to the keyboard height so you can still scroll the whole content
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbFrame.size.height, 0.0);
_scrollView.contentInset = contentInsets;
_scrollView.scrollIndicatorInsets = contentInsets;
}
- (void)keyboardWillHide:(NSNotification*)aNotification{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
_scrollView.contentInset = contentInsets;
_scrollView.scrollIndicatorInsets = contentInsets;
}
Dies ist die Lösung mit Swift.
import UIKit
class ExampleViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var scrollView: UIScrollView!
@IBOutlet var textField1: UITextField!
@IBOutlet var textField2: UITextField!
@IBOutlet var textField3: UITextField!
@IBOutlet var textField4: UITextField!
@IBOutlet var textField5: UITextField!
var activeTextField: UITextField!
// MARK: - View
override func viewDidLoad() {
super.viewDidLoad()
self.textField1.delegate = self
self.textField2.delegate = self
self.textField3.delegate = self
self.textField4.delegate = self
self.textField5.delegate = self
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.registerForKeyboardNotifications()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.unregisterFromKeyboardNotifications()
}
// MARK: - Keyboard
// Call this method somewhere in your view controller setup code.
func registerForKeyboardNotifications() {
let center: NSNotificationCenter = NSNotificationCenter.defaultCenter()
center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}
func unregisterFromKeyboardNotifications () {
let center: NSNotificationCenter = NSNotificationCenter.defaultCenter()
center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
// Called when the UIKeyboardDidShowNotification is sent.
func keyboardWasShown (notification: NSNotification) {
let info : NSDictionary = notification.userInfo!
let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size
let contentInsets: UIEdgeInsets = 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.
var aRect = self.view.frame
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.activeTextField.frame.Origin) ) {
self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
}
}
// Called when the UIKeyboardWillHideNotification is sent
func keyboardWillBeHidden (notification: NSNotification) {
let contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
// MARK: - Text Field
func textFieldDidBeginEditing(textField: UITextField) {
self.activeTextField = textField
}
func textFieldDidEndEditing(textField: UITextField) {
self.activeTextField = nil
}
}
Sie müssen scrollview programmgesteuert mit einer bestimmten Bildgröße hinzufügen. Sie müssen UIScrollViewDelegate in der .h-Datei hinzufügen. Sie müssen die Scrollansicht aktivieren, die Sie in viewDidLoad () schreiben müssen.
scrollview.scrollEnabled=YES;
scrollview.delegate=self;
scrollview.frame = CGRectMake(x,y,width,height);
//---set the content size of the scroll view---
[scrollview setContentSize:CGSizeMake(height,width)];
Auf diese Weise können Sie die Werte für x, y, Breite und Höhe hinzufügen. Ich denke, das wird Ihnen helfen.
Versuche dies:
-(void)textFieldDidBeginEditing:(UITextField *)sender
{
if ([sender isEqual:self.m_Sp_Contact])
{
[self.m_Scroller setContentOffset:CGPointMake(0, 105)animated:YES];
}
}
Swift 2.0:
Fügen Sie eine UIScrollView und TextFields oben hinzu. Machen Sie Storyboard-Referenzen zu VC.
@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var scrollView: UIScrollView!
Fügen Sie diese Methoden hinzu: UITextFieldDelegate & UIScrollViewDelegate.
//MARK:- TEXTFIELD METHODS
func textFieldShouldReturn(textField: UITextField) -> Bool {
if(username.returnKeyType == UIReturnKeyType.Default) {
password.becomeFirstResponder()
}
textField.resignFirstResponder()
return true
}
func textFieldDidBeginEditing(textField: UITextField) {
dispatch_async(dispatch_get_main_queue()) {
let scrollPoint:CGPoint = CGPointMake(0,textField.frame.Origin.y/4)
self.scrollView!.setContentOffset(scrollPoint, animated: true);
}
}
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
dispatch_async(dispatch_get_main_queue()) {
UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true) })
}
return true
}
override func touchesBegan(touches: Set<UITouch>,
withEvent event: UIEvent?) {
self.view.endEditing(true)
}
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
self.scrollView.scrollEnabled = true
dispatch_async(dispatch_get_main_queue()) {
UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true)
})
}
}
Hier finden Sie eine kostenlose Bibliothek für das Tastaturhandling Keyboard-Handling-in-iPhone-Applications . Sie müssen nur eine Codezeile schreiben:
[AutoScroller addAutoScrollTo:scrollView];
Es ist großartig, mit der Tastatur in Formularen umzugehen
Ich denke, der beste Ansatz ist die Verwendung einer protokollorientierten Programmierung, wenn Sie Swift verwenden.
Als erstes müssen Sie ein KeyboardCapable
-Protokoll erstellen, das jedem UIViewController, der diesem entspricht, die Möglichkeit gibt, Tastaturbeobachter zu registrieren und die Registrierung aufzuheben:
import Foundation
import UIKit
protocol KeyboardCapable: KeyboardAnimatable {
func keyboardWillShow(notification: NSNotification)
func keyboardWillHide(notification: NSNotification)
}
extension KeyboardCapable where Self: UIViewController {
func registerKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil)
}
func unregisterKeyboardNotifications() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
}
Sie haben das überflüssige KeyboardAnimatable
-Schlüsselwort in dem obigen Code festgestellt. Es ist nur der Name des nächsten Protokolls, das wir erstellen müssen:
import Foundation
import UIKit
protocol KeyboardAnimatable {
}
extension KeyboardAnimatable where Self: UIViewController {
func performKeyboardShowFullViewAnimation(withKeyboardHeight height: CGFloat, andDuration duration: NSTimeInterval) {
UIView.animateWithDuration(duration, animations: { () -> Void in
self.view.frame = CGRectMake(view.frame.Origin.x, -height, view.bounds.width, view.bounds.height)
}, completion: nil)
}
func performKeyboardHideFullViewAnimation(withDuration duration: NSTimeInterval) {
UIView.animateWithDuration(duration, animations: { () -> Void in
self.view.frame = CGRectMake(view.frame.Origin.x, 0.0, view.bounds.width, view.bounds.height)
}, completion: nil)
}
}
Dieses KeyboardAnimatable
-Protokoll gibt allen UIViewController-Konformaten zwei Methoden, mit denen die gesamte Ansicht nach oben bzw. unten animiert wird.
Okay, wenn KeyboardCapable
mit KeyboardAnimatable
übereinstimmt, entsprechen alle UIViewController, die KeyboardCapable
entsprechen, auch KeyboardAnimatable
. Das ist cool.
Lassen Sie uns eine UIViewController
-konforme KeyboardCapable
sehen, die auf Tastaturereignisse reagiert:
import Foundation
import UIKit
class TransferConfirmViewController: UIViewController, KeyboardCapable {
//MARK: - LIFE CYCLE
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
registerKeyboardNotifications()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
unregisterKeyboardNotifications()
}
//MARK: - NOTIFICATIONS
//MARK: Keyboard
func keyboardWillShow(notification: NSNotification) {
let keyboardHeight = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
performKeyboardShowFullViewAnimation(withKeyboardHeight: keyboardHeight, andDuration: animationDuration)
}
func keyboardWillHide(notification: NSNotification) {
let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
performKeyboardHideFullViewAnimation(withDuration: animationDuration)
}
}
Jetzt reagiert Ihre UIViewController
auf Tastaturereignisse und wird in der Folge animiert.
Hinweis: Wenn Sie anstelle von Push oder Pull die Ansicht eine benutzerdefinierte Animation erstellen möchten, müssen Sie benutzerdefinierte Methoden für das Protokoll KeyboardAnimatable
definieren oder sie für Funktionen der Funktion KeyboardCapable
ausführen. Es liegt an dir.
Eine viel elegantere Lösung ist die Verwendung einer UIView
-Unterklasse (obwohl dies nicht immer angemessen ist), und alle Unteransichten für den Frame-Wechsel eines Elternteils neu berechnen (und seien Sie intelligent: nur neu berechnen, wenn sich die neue Frame-Größe geändert hat, dh verwendet wird) CGRectEqualToRect
, um den neuen Frame zu vergleichen, wenn Sie setFrame
überschreiben und VOR dem Aufruf von [super setFrame:frame_]
). Der einzige Haken dabei ist, dass das UIViewController
, das Sie verwenden möchten, wahrscheinlich Tastaturereignisse hören sollte (oder Sie könnten es im UIView
selbst tun, um die Kapselung zu erleichtern). Aber nur UIKeyboardWillShowNotification
und UIKeyboardWillHideNotification
. Dies ist nur so, dass es glatt aussieht (wenn Sie darauf warten, dass CG es anruft, erhalten Sie einen Moment der Abgeschlagenheit).
Dies hat den Vorteil, dass eine UIView
-Unterklasse erstellt wird, die ohnehin das Richtige tut.
Die naive Implementierung wäre, drawRect:
(nicht) zu überschreiben. Besser wäre es, layoutSubviews
zu verwenden (und dann in UIViewController
oder was auch nicht. Sie können [view setNeedsLayout
] in einer SINGLE-Methode aufrufen, die entweder show oder aufgerufen wird verbergen).
Diese Lösung vermeidet die Hardcodierung eines Tastatur-Offsets (der sich ändert, wenn sie nicht aufgeteilt sind usw.). Dies bedeutet auch, dass Ihre Ansicht eine Unteransicht vieler anderer Ansichten sein kann und dennoch ordnungsgemäß reagiert.
Hardcode so etwas nicht, wenn es keine andere Lösung gibt. Das Betriebssystem gibt Ihnen genug Informationen, wenn Sie alles richtig gemacht haben, dass Sie nur intelligent neu zeichnen müssen (basierend auf Ihrer neuen frame
-Größe). Das ist viel sauberer und so wie du sollte Dinge tun. (Es kann jedoch einen noch besseren Ansatz geben.)
Prost.
Es ist sehr einfach, einfach folgenden Code in Ihre Klasse einzufügen und bei Bedarf anzupassen.
-(void)textFieldDidBeginEditing:(UITextField *)textField {
//Show Keyboard
self.view.frame = CGRectMake(self.view.frame.Origin.x,
self.view.frame.Origin.y-50,
self.view.frame.size.width,
self.view.frame.size.height);
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
// Hide keyboard
self.view.frame = CGRectMake(self.view.frame.Origin.x,
self.view.frame.Origin.y+50,
self.view.frame.size.width,
self.view.frame.size.height);
}
Sie können dies auch tun, indem Sie Textfeld-Delegatmethoden verwenden. Überprüfen Sie den Code unten. Es funktioniert für mich, wenn das Textfeld in der Bildlaufansicht platziert wird.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if(textField == answer)
{
CGPoint cPoint = textField.frame.Origin;
[scrollView setContentOffset:CGPointMake(0, cPoint.y - 100) animated:YES];
}
}
Hinweis: Sie müssen den Wert von cPoint.y - 100 entsprechend Ihrer Ansicht ändern.
Hier ist meine Version mit Autolayout:
Die Idee ist nur, Ihre Ansicht, die Textfelder/Textansicht enthält, in eine UIScrollView einzubetten, eine Einschränkung von unten auf den Übersichtsbereich festzulegen, einen Ausgang zu erstellen und ihn anhand der Tastaturhöhe mithilfe von Benachrichtigungen zu aktualisieren. Dies basiert auf dem Beispiel von Apple hier und technischer Hinweis von Apple zu UIScrollView mit AutoLayout hier .
1) Betten Sie Ihre Ansicht V in eine UIScrollView S: Wenn Sie bereits Konstanten und Unteransichten festgelegt haben, können Sie Ihre Ansicht und Unteransichten in die Ansicht des ViewControllers kopieren/einfügen, sie dann über das Menü Editor -> Einbetten einbetten und schließlich löschen die kopierten Ansichten.)
2) Legen Sie die folgenden Bedingungen fest:
S nach Übersehen: 0
V top Platz zum Superview: 0
V führender Platz zum Überblick: 0
V gleich Breite zu S
Letzte Untersicht für Untersicht: 20
3) Erstellen Sie einen Auslass aus der neuesten Einschränkung für Ihren View-Controller
4) Verwenden Sie den folgenden Code:
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomSpaceToContentView;
// ...
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// ...
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Handle keyboard
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
self.bottomSpaceToContentView.constant = kBottomMargin + kbSize.height;
[self.view layoutIfNeeded];
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
self.bottomSpaceToContentView.constant = kBottomMargin;
[self.view layoutIfNeeded];
}
Und tadaaaaa, es funktioniert!
Es gibt viele Antworten, die den Ansatz erklären. Ich habe den gleichen Ansatz gewählt, aber die Implementierung ist nicht gut.
Hier ist die Basis Idee . Ich habe Änderungen an der keyboardWasShown-Methode vorgenommen.
{
// Obtain keyboard Info
NSDictionary* info = [notification userInfo];
CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
// Obtain ScrollView Info w.r.t. top View
CGRect scrollViewRect = [self.view convertRect:self.scrollView.frame fromView:nil];
// Depending upon your screen Ui, Scroll View's bottom Edge might be at some offset from screen's bottom
// Calculate the exact offset
int scrollViewBottomOffset = self.view.frame.size.height - (scrollViewRect.Origin.y + scrollViewRect.size.height);
int heightToBeAdjusted = keyboardRect.size.height - scrollViewBottomOffset;
// We may also need to consider the Insets if already present with ScrollView. Let's keep it simple for now
// But we should store these, so that we can restore the Insets when Keyboard is gone
// origInsets = self.scrollView.contentInset;
// Set the new Insets for ScrollView
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, heightToBeAdjusted, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// Visible frame (not overlapped by Keyboard)
CGRect visibleFrame = self.view.frame;
visibleFrame.size.height -= keyboardRect.size.height;
// Get the Rect for Textfield w.r.t self.view
CGRect activeFieldFrame = self.activeField.frame;
activeFieldFrame = [self.view convertRect:activeFieldFrame fromView:self.scrollView];
// Check if the TextField is Visible or not
if (!CGRectContainsRect(visibleFrame, activeFieldFrame) ) {
// Scroll to make it visible but for scrolling use the activeField frame w.r.t. to scroll View
[self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
}
}
Fügen Sie diese Methode hinzu, um das activeField zu initialisieren
- (IBAction)textFieldDidBeginEditing:(UITextField *)sender
{
self.activeField = sender;
}
Dies ist eine geräteunabhängige Offsetberechnung. Ruft die überlappte Höhe zwischen Tastatur und Textfeld ab:
func keyboardShown(notification: NSNotification) {
let info = notification.userInfo!
let value: AnyObject = info[UIKeyboardFrameEndUserInfoKey]!
let rawFrame = value.CGRectValue
let keyboardFrame = view.convertRect(rawFrame, fromView: nil)
let screenHeight = UIScreen.mainScreen().bounds.size.height;
let Ylimit = screenHeight - keyboardFrame.size.height
let textboxOriginInSuperview:CGPoint = self.view.convertPoint(CGPointZero, fromCoordinateSpace: lastTextField!)
self.keyboardHeight = (textboxOriginInSuperview.y+self.lastTextField!.frame.size.height) - Ylimit
if(self.keyboardHeight>0){
self.animateViewMoving(true, moveValue: keyboardHeight!)
}else{
keyboardHeight=0
}
}
keyBoardHeight ist der Versatz.
https://github.com/michaeltyson/TPKeyboardAvoiding Laden Sie diese Datei herunter und fügen Sie eine benutzerdefinierte Klasse hinzu. Wenn Sie diese Option in Ihrer Tabellenansicht verwenden, werden alle Dinge verwaltet Tastatur zu vermeiden
hier ist eine UITextfield-Kategorie (und andere ähnliche Felder), die ich vorgenommen habe, um das Textfeld von der Tastatur zu entfernen. Sie sollten es in der Lage sein, dieses in Ihrem View-Controller abzulegen. Der gesamte Bildschirm wird nach oben verschoben, sodass sich das aktuelle Textfeld mit Animationen über der Tastatur befindet
#import "UIView+avoidKeyboard.h"
#import "AppDelegate.h"
@implementation UIView (avoidKeyboard)
- (void) becomeFirstResponder {
if(self.isFirstResponder)
return;
[super becomeFirstResponder];
if ([self isKindOfClass:[UISearchBar class]] ||
[self isKindOfClass:[UITextField class]] ||
[self isKindOfClass:[UITextView class]])
{
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
CGRect screenBounds = appDelegate.window.frame;
CGFloat keyboardHeight;
CGFloat keyboardY;
CGFloat viewsLowestY;
CGPoint Origin = [self.superview convertPoint:self.frame.Origin toView:appDelegate.window]; //get this views Origin in terms of the main screens bounds
if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){ //the window.frame doesnt take its orientation into account so if its sideways we must use the x value of the Origin instead of the y
keyboardHeight = 216;
keyboardY = screenBounds.size.height - keyboardHeight; //find the keyboards y coord relative to how much the main window has moved up
viewsLowestY = Origin.y + self.frame.size.height; //find the lowest point of this view
}
else {
keyboardHeight = 162;
keyboardY = screenBounds.size.width - keyboardHeight;
viewsLowestY = Origin.x + self.frame.size.height;
}
CGFloat difference = viewsLowestY - keyboardY + 20; //find if this view overlaps with the keyboard with some padding
if (difference > 0){ //move screen up if there is an overlap
[UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
CGRect frame = appDelegate.window.frame;
if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){
frame.Origin.y -= difference;
}
else {
frame.Origin.x -= difference;
}
appDelegate.window.frame = frame;
}
completion:nil];
}
}
}
//look at appDelegate to see when the keyboard is hidden
@end
Fügen Sie in Ihrer appDelegate diese Funktion hinzu
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHides:) name:UIKeyboardWillHideNotification object:nil]; //add in didFinishLaunchingWithOptions
...
- (void)keyboardHides:(NSNotification *)notification
{
[UIView animateWithDuration:0.3 animations:^{
[window setFrame: CGRectMake(0, 0, window.frame.size.width, window.frame.size.height)];
} completion:nil];
}
Bitte folgen Sie diesen Schritten.
1) Deklarieren Sie die folgende Variable in der .h-Datei.
{
CGFloat animatedDistance;
}
2) Deklarieren Sie die folgenden Konstanten in der .m-Datei.
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;
3) Verwenden Sie den UITextField-Delegaten, um die Tastatur nach oben/unten zu verschieben.
-(void) textFieldDidBeginEditing:(UITextField *)textField
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat midline = textFieldRect.Origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =
midline - viewRect.Origin.y
- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =
(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0)
{
heightFraction = 0.0;
}
else if (heightFraction > 1.0)
{
heightFraction = 1.0;
}
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait)
{
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
CGRect viewFrame = self.view.frame;
viewFrame.Origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
{
CGRect viewFrame = self.view.frame;
viewFrame.Origin.y += animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
}
Ich wickle alles in eine Klasse. Rufen Sie einfach diese Codezeilen auf, wenn Ihr Viewcontroller geladen ist:
- (void)viewDidLoad {
[super viewDidLoad];
KeyboardInsetScrollView *injectView = [[KeyboardInsetScrollView alloc] init];
[injectView injectToView:self.view withRootView:self.view];
}
Hier ist ein Link zum Beispielprojekt:
https://github.com/caohuuloc/KeyboardInsetScrollView
Vor kurzem befand ich mich bei der Arbeit an einer Messaging-App in einem ähnlichen Szenario. Ich habe ein benutzerdefiniertes UIView erstellt, das am oberen Rand der Tastatur haftet und das meiste, was Sie benötigen, automatisch ausführt
http://www.thegameengine.org/wp-content/uploads/2013/11/message_composer_quad_1.jpg
Die Idee hinter diesem Projekt war, etwas zu erstellen, das der iMessage-Kompositionsansicht AKA ähnelt:
Um die Größe Ihres UIScrollView zu ändern oder neu zu konfigurieren, verwenden Sie die folgende optionale Delegierungsmethode:
- (void)messageComposerFrameDidChange:(CGRect)frame withAnimationDuration:(float)duration;
Sie wird aufgerufen, wenn der Frame geändert (in der Größe geändert, neu positioniert, gedreht) wird, und liefert auch die Animationsdauer. Sie können diese Informationen verwenden, um die Größe des Rahmens und der Inhalte Ihres UIScrollView nach Bedarf zu ändern.
Fügen Sie diese einfach Ihrer Pod-Datei hinzu -> pod 'IQKeyboardManager'
Das ist es, alle Tastaturen und Scrollviews und alles!
Sie müssen nichts kodieren, könnte keine bessere Lösung finden!
Es hat eine Erweiterung, die die Anzeige von Textfeldern, die Bildschirmverschiebung sowie die nächsten und vorherigen Pfeile übernimmt, wenn mehrere Textfelder vorhanden sind.
Es hat auch eine benutzerdefinierte Schaltfläche, die entfernt werden kann.
Ich habe festgestellt, dass dies die beste Lösung ist. Folgen Sie dem nachstehenden Code:
Befestigen Sie das unten stehende an Ihre Vertical Space - Bottom Layout Guide - TextField
-Einschränkung.
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst;
Zweitens fügen Sie Beobachter für Tastaturbenachrichtigungen hinzu.
- (void)observeKeyboard {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
Fügen Sie dies Ihrer viewDidLoad
hinzu.
[self observeKeyboard];
Schließlich die Methoden, mit denen Tastaturänderungen vorgenommen werden.
- (void)keyboardWillShow:(NSNotification *)notification {
//THIS WILL MAKE SURE KEYBOARD DOESNT JUMP WHEN OPENING QUICKTYPE/EMOJI OR OTHER KEYBOARDS.
kbHeight = 0;
height = 0;
self.textViewBottomConst.constant = height;
self.btnViewBottomConst.constant = height;
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [kbFrame CGRectValue];
CGRect finalKeyboardFrame = [self.view convertRect:keyboardFrame fromView:self.view.window];
int kbHeight = finalKeyboardFrame.size.height;
int height = kbHeight + self.textViewBottomConst.constant;
self.textViewBottomConst.constant = height;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
self.textViewBottomConst.constant = 10;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
Eine viel einfachere und dennoch verallgemeinerte Methode, genau wie Apple, indem die Höhe der Tastaturen berücksichtigt wird. Dies ist sehr hilfreich, wenn wir eine benutzerdefinierte Symbolleiste auf der Tastatur verwenden Obwohl Apples Ansatz here einige Probleme hat.
Hier ist meine Herangehensweise (leicht modifizierter Weg von Apple) -
// UIKeyboardDidShowNotification
- (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);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
// UIKeyboardWillHideNotification
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
Ich weiß, dass dies zu spät ist, aber ich wollte den zukünftigen Besuchern vor allem meine Art und Weise mitteilen. Viele gute Methoden wurden geteilt, aber es hat mir nicht gefallen, wie die Benutzeroberfläche total schlecht wird. Es gibt eine einfache Methode, die zwei Teile umfasst: -
CGAffineTransform(TranslationX: x, TranslationY: y)
, um die erstellte Ansicht über die Tastatur zu verschieben. Ich weiß, dass es sehr einfach erscheint, aber es ist wirklich effektiv und ordentlich .
Eine einfache Lösung, die den UIViewController erweitert
https://github.com/damienromito/VisibleFormViewController
Einfache Lösung und mit der neuesten Animations-API. Wenn Sie den Origin.y um 215 ändern, können Sie ihn an den für Sie geeigneten Wert anpassen.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if (self.view.frame.Origin.y >= 0) {
[UIView animateWithDuration:0.5 animations:^{
self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y-215, self.view.frame.size.width, self.view.frame.size.height);
}];
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (self.view.frame.Origin.y < 0) {
[UIView animateWithDuration:0.5 animations:^{
self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y+215, self.view.frame.size.width, self.view.frame.size.height);
}];
}
}
Ich möchte die Antwort von @sumanthkodi erweitern.
Wie einige Leute bereits sagten, funktioniert sein Ansatz in neueren Implementierungen nicht, da sich der UIView nicht bewegt, wenn Sie constraints verwenden.
Ich habe den Code wie folgt bearbeitet (und auf Swift 2.0 portiert) und hoffe, dass er einigen Leuten hilft:
1) Referenzieren Sie die vertikale Einschränkung der Ansicht, die Sie nach oben verschieben möchten:
@IBOutlet var viewConstraint: NSLayoutConstraint!
Stellen Sie sicher, dass Sie diese Variable in Ihrem Storyboard mit der Einschränkung referenzieren.
2) Fügen Sie den Delegierten hinzu und implementieren Sie die Listener. Dies ist die gleiche Implementierung wie zuvor:
class YourViewController: UIViewController, UITextFieldDelegate {
...
func textFieldDidBeginEditing(textField: UITextField) {
animateTextField(textField, up: true)
}
func textFieldDidEndEditing(textField: UITextField) {
animateTextField(textField, up: false)
}
...
}
3) Fügen Sie Ihre Animationsmethode animateTextField
zur YourViewController
-Klasse hinzu. Legen Sie den temporären Einschränkungswert nach Bedarf fest.
func animateTextField(textfield: UITextField, up: Bool) {
let originalConstraint = 50
let temporaryConstraint = 0
let movementDuration = 0.3
let constraint = CGFloat(up ? temporaryConstraint : originalConstraint)
containerViewConstraint.constant = constraint
UIView.animateWithDuration(movementDuration) {
self.view.layoutIfNeeded()
}
}
Das wird perfekt funktionieren. Die Bildlaufansicht wird durch die Textfeldposition automatisch angepasst
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.25;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;
@interface LoginVC ()
{
CGFloat animatedDistance;
CGRect viewFrameKey;
}
//In ViewDidLoad
viewFrameKey=self.view.frame;
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect textFieldRect =
[self.view.window convertRect:textField.bounds fromView:textField];
CGRect viewRect =
[self.view.window convertRect:self.view.bounds fromView:self.view];
CGFloat midline = textFieldRect.Origin.y + 0.5 * textFieldRect.size.height;
CGFloat numerator =
midline - viewRect.Origin.y
- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator =
(MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0)
{
heightFraction = 0.0;
}
else if (heightFraction > 1.0)
{
heightFraction = 1.0;
}
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
CGRect viewFrame = self.view.frame;
viewFrame.Origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrameKey];
[UIView commitAnimations];
}
Ich habe gerade diese Klasse gefunden:
https://github.com/OliverLetterer/SLScrollViewKeyboardSupport
Und bisher funktioniert es auf dem iPhone sehr gut, einschließlich Animationen und korrektem Offset.
Um es zu verwenden, fügen Sie einfach viewDidLoad
hinzu:
self.support = [[SLScrollViewKeyboardSupport alloc] initWithScrollView:self.scrollView];
Eine sehr leichte Lösung könnte mit KeyboardAnimator sein.
projekt hat die Beispielimplementierung erhalten, die Dokumentation ist noch in Bearbeitung ...
Bestimmungsgemäße Verwendung :: Es gibt eine spezielle Implementierung für UITextField & UITextView
Limitation :: Es ist voll auf Ziel-c, die Swift-Version wird bald verfügbar sein.
Dieser Teil des Codes berechnet anhand der Höhe der Tastatur und der Tiefe des Textfelds, wie viel Bewegung erforderlich ist. Denken Sie daran, UITextFieldDelegate in Ihre Kopfzeile zu delegieren und zu erben.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[_tbxUsername resignFirstResponder];
[_tbxPassword resignFirstResponder];
}
- (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
{
int animatedDistance;
int moveUpValue = textField.frame.Origin.y+ textField.frame.size.height;
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = 236-(460-moveUpValue-5);
}
else
{
animatedDistance = 182-(320-moveUpValue-5);
}
if(animatedDistance>0)
{
const int movementDistance = animatedDistance;
const float movementDuration = 0.3f;
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: nil context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
}
Delegieren Sie bei ViewDidLoad hinzu
_tbxUsername.delegate = self;
_tbxPassword.delegate = self;
Auf Ihrem ViewController:
@IBOutlet weak var usernameTextfield: UITextField!
@IBOutlet weak var passwordTextfield: UITextField!
@IBOutlet weak var loginScrollView: UIScrollView!
override func viewWillAppear(animated: Bool) {
loginScrollView.scrollEnabled = false
}
TextFeld-Delegaten hinzufügen.
//MARK:- TEXTFIELD METHODS
func textFieldShouldReturn(textField: UITextField) -> Bool
{
if (usernameTextfield.resignFirstResponder())
{
passwordTextfield.becomeFirstResponder()
}
textField.resignFirstResponder();
loginScrollView!.setContentOffset(CGPoint.zero, animated: true);
loginScrollView.scrollEnabled = false
return true
}
func textFieldDidBeginEditing(textField: UITextField)
{
loginScrollView.scrollEnabled = true
if (textField.tag == 1 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
{
let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.Origin.y/6.4);
loginScrollView!.setContentOffset(scrollPoint, animated: true);
}
else if (textField.tag == 2 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
{
let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.Origin.y/6.0);
loginScrollView!.setContentOffset(scrollPoint, animated: true);
}
}
func textFieldDidEndEditing(textField: UITextField)
{
loginScrollView!.setContentOffset(CGPointZero,animated: true);
}
Scrollansicht in Ansicht einstellen
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGPoint point;
if(textField == txtEmail){
// -90 is for my you can change as per your postion
point = CGPointMake(0, textField.frame.Origin.y - 90);
}
else if (textField == txtContact){
point = CGPointMake(0, textField.frame.Origin.y - 90);
}
[scrollV setContentOffset:point animated:YES];
}
Bitte fügen Sie diese Zeilen in die Textfeld-Delegatenmethode ein, um im iPad nach oben zu scrollen.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeTextfield = textField;
CGPoint pt;
CGRect rc = [textField bounds];
rc = [textField convertRect:rc toView:scrlView];
pt = rc.Origin;
pt.x = 0;
pt.y -= 100;
[scrlView setContentOffset:pt animated:YES];
scrlView.contentSize = CGSizeMake(scrlView.frame.size.width, button.frame.Origin.y+button.frame.size.height + 8 + 370);
}
Versuchen Sie die IQKeyboard-Bibliothek.
Dadurch wird das Textfeld automatisch nach oben verschoben.
Dies kann einfach mit untersten Codezeilen unter Verwendung von Einschränkungen erreicht werden
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
[self adjustTextViewByKeyboardState:YES keyboardInfo:[notification userInfo]];
}
- (void)keyboardWillHide:(NSNotification *)notification {
[self adjustTextViewByKeyboardState:NO keyboardInfo:[notification userInfo]];
}
- (void)viewDidDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super viewDidDisappear:animated];
}
- (void)adjustTextViewByKeyboardState:(BOOL)showKeyboard keyboardInfo:(NSDictionary *)info {
CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat height = keyboardFrame.size.height;
self.constraintToAdjust.constant = height; UIViewAnimationCurve animationCurve = [info[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
UIViewAnimationOptions animationOptions = UIViewAnimationOptionBeginFromCurrentState;
if (animationCurve == UIViewAnimationCurveEaseIn) {
animationOptions |= UIViewAnimationOptionCurveEaseIn;
}
else if (animationCurve == UIViewAnimationCurveEaseInOut) {
animationOptions |= UIViewAnimationOptionCurveEaseInOut;
}
else if (animationCurve == UIViewAnimationCurveEaseOut) {
animationOptions |= UIViewAnimationOptionCurveEaseOut;
}
else if (animationCurve == UIViewAnimationCurveLinear) {
animationOptions |= UIViewAnimationOptionCurveLinear;
}
[UIView animateWithDuration:[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0 options:animationOptions animations:^{
[self.view layoutIfNeeded];
} completion:nil];
}
Wir sollten den exakten Schnittbereich (Tastaturrahmen und Rahmen des Textfelds) berechnen, der ausgeblendet ist, und dann den Rahmen der Ansicht ändern.
Hier gebe ich ein vollständiges Beispiel.
3 für variabel erklären
#define PADDING 10
@interface PKViewController () @property (nonatomic, assign) CGRect originalViewFrame; //original view's frame @property (nonatomic, strong) UITextField *activeTextField; // current text field @property (nonatomic, assign) CGRect keyBoardRect; // covered area by keaboard @end
Speichern Sie den Originalrahmen
- (void)viewDidLoad {
[super viewDidLoad];
_originalViewFrame = self.view.frame;
}
Fügen Sie Ihren View-Controller als Beobachter für die Tastaturbenachrichtigung hinzu
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
Beobachter entfernen
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Speichern Sie den von der Tastatur abgedeckten Bereich, wenn diese angezeigt wird, und setzen Sie sie auf CGRectZero, wenn sie nicht mehr angezeigt wird
- (void)keyboardWasShown:(NSNotification *)notification{
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
_keyBoardRect = CGRectMake(0, _originalViewFrame.size.height - keyboardSize.height, keyboardSize.width, keyboardSize.height);
[self moveTextFieldUP];
}
- (void) keyboardWillHide:(NSNotification *)notification{
_keyBoardRect = CGRectZero;
[self setDefaultFrame];
}
Speichern Sie das aktive Textfeld
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
_activeTextField = textField;
//When keyboard is already present but the textfield is hidden. Case:When return key of keyboard makes the next textfield as first responder
if (!CGRectIsEmpty(_keyBoardRect)) {
[self moveTextFieldUP];
}
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
Jetzt sollten wir den Rahmen der Ansicht ändern
- (void)moveTextFieldUP{
CGRect virtualTextFieldRect = CGRectMake(0, self.view.frame.Origin.y, _activeTextField.frame.size.width, _activeTextField.frame.Origin.y+_activeTextField.frame.size.height);
if (CGRectIntersectsRect(_keyBoardRect, virtualTextFieldRect)) {
CGRect intersectRect = CGRectIntersection(_keyBoardRect, virtualTextFieldRect);
CGFloat newY = _originalViewFrame.Origin.y - intersectRect.size.height;
CGFloat newHeight = _originalViewFrame.size.height + intersectRect.size.height;
CGRect newFrame = CGRectMake(0, newY-PADDING, _originalViewFrame.size.width, newHeight+PADDING);
[UIView animateWithDuration:0.3 animations:^{
[self.view setFrame:newFrame];
}];
NSLog(@"Intersect");
}
}
- (void)setDefaultFrame {
[UIView animateWithDuration:0.3 animations:^{
[self.view setFrame:_originalViewFrame];
}];
}
Viele Antworten hier, aber das funktioniert und ist viel kürzer als die meisten:
- (void)textFieldDidBeginEditing:(UITextField *)sender
{
UIScrollView *scrollView = (UIScrollView *)self.view; // assuming this method is pasted into the UIScrollView's controller
const double dontHardcodeTheKeyboardHeight = 162;
double textY = [sender convertPoint:CGPointMake(0, 0) toView:scrollView].y;
if (textY - scrollView.contentOffset.y + sender.frame.size.height > self.view.frame.size.height - dontHardcodeTheKeyboardHeight)
[scrollView setContentOffset:CGPointMake(0.0, textY - 10) animated:YES];
}
Kann leicht und automatisch durchgeführt werden, wenn sich dieses Textfeld in einer Tabellenzelle befindet (auch wenn table.scrollable = NO ist).
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField {
[self slideUp];
return YES;
}
-(BOOL) textFieldShouldEndEditing:(UITextField *)textField {
[self slideDown];
return YES;
}
#pragma mark - Slide Up and Down animation
- (void) slideUp {
[UIView beginAnimations:nil context:nil];
layoutView.frame = CGRectMake(0.0, -70.0, layoutView.frame.size.width, layoutView.frame.size.height);
[UIView commitAnimations];
}
- (void) slideDown {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelay: 0.01];
layoutView.frame = CGRectMake(0.0, 0.0, layoutView.frame.size.width, layoutView.frame.size.height);
[UIView commitAnimations];
}
Obwohl dieser Thread über genügend Antworten verfügt, möchte ich einen viel einfacheren, aber verallgemeinerten Weg vorschlagen, genauso wie Apple dies tut, indem er die Höhe der Tastaturen berücksichtigt. Dies ist sehr hilfreich, wenn wir eine benutzerdefinierte Symbolleiste auf der Tastatur verwenden hier hat wenige Probleme.
Hier ist meine Herangehensweise (leicht modifizierter Weg von Apple) -
// 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);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
es ist einfach:-
In TextFieldDidBeginEditing: -
self.view.frame=CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y-150, self.view.frame.size.width, self.view.frame.size.height);
In TextFieldShouldEndEditing: -
self.view.frame=CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y+150, self.view.frame.size.width, self.view.frame.size.height);
Mit IQKeyboardManager scrollen UITextField und UITextView automatisch, wenn die Tastatur angezeigt wird. Git link: https://github.com/hackiftekhar/IQKeyboardManager .
pod: Pod 'IQKeyboardManager' # iOS8 und höher
pod 'IQKeyboardManager', '3.3.7' # iOS7
Einfache Lösung für Scrollview mit TextFields ist unten. Keine Einschränkungen oder aktives Textfeld usw.
override func viewWillAppear(_ animated: Bool){
super.viewWillAppear(animated)
registerForKeyboardNotifications();
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
deregisterFromKeyboardNotifications();
}
//MARK:- KEYBOARD DELEGATE METHODS
func registerForKeyboardNotifications(){
//Adding notifies on keyboard appearing
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func deregisterFromKeyboardNotifications(){
//Removing notifies on keyboard appearing
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWasShown(notification: NSNotification){
var info = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
var contentInset:UIEdgeInsets = self.scrRegister.contentInset
contentInset.bottom = (keyboardSize?.height)!
scrRegister.contentInset = contentInset
}
func keyboardWillBeHidden(notification: NSNotification)
{
var contentInset:UIEdgeInsets = self.scrRegister.contentInset
contentInset.bottom = 0
scrRegister.contentInset = contentInset
}
Bitte befolgen Sie diese Schritte, es kann hilfreich sein . Legen Sie eine Ansicht und dann Ihr Textfeld in dieser Ansicht fest, und erkennen Sie das Ereignis per Delegat, wenn Ihre Tastatur hochgefahren wird. Animieren Sie zu diesem Zeitpunkt die Ansicht nach oben (Sie können eine Position zuweisen.) (auch für diese Ansicht), dann würde Ihre Ansicht zu dieser Position gehen. Machen Sie dasselbe, um die Ansicht nach unten zu animieren.
Vielen Dank
Swift 3.0-Version von Apples Tastaturverwaltungscode ist hier: FloatingTF Im folgenden Code wird ein Textfeld auf Materialdesign-Basis in iOS verwendet.
import UIKit
class SignupViewController: UIViewController, UITextFieldDelegate {
//MARK: - IBOutlet:
@IBOutlet weak var emailTF: FloatingTF!
@IBOutlet weak var passwordTF: FloatingTF!
@IBOutlet weak var dobTF: FloatingTF!
@IBOutlet weak var scrollView: UIScrollView!
//MARK: - Variable:
var activeTextField: UITextField!
//MARK: - ViewController Lifecycle:
override func viewDidLoad() {
super.viewDidLoad()
emailTF.delegate = self
passwordTF.delegate = self
dobTF.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
registerKeyboardNotifications()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
deRegisterKeyboardNotifications()
}
//MARK: - Keyboard notification observer Methods
fileprivate func registerKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
fileprivate func deRegisterKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: self.view.window)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: self.view.window)
}
func keyboardWillShow(notification: NSNotification) {
let info: NSDictionary = notification.userInfo! as NSDictionary
let value: NSValue = info.value(forKey: UIKeyboardFrameBeginUserInfoKey) as! NSValue
let keyboardSize: CGSize = value.cgRectValue.size
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.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.
var aRect: CGRect = self.view.frame
aRect.size.height -= keyboardSize.height
let activeTextFieldRect: CGRect? = activeTextField?.frame
let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.Origin
if (!aRect.contains(activeTextFieldOrigin!)) {
scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true)
} }
func keyboardWillHide(notification: NSNotification) {
let contentInsets: UIEdgeInsets = .zero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}
//MARK: - UITextField Delegate Methods
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == emailTF {
passwordTF.becomeFirstResponder()
}
else if textField == passwordTF {
dobTF.becomeFirstResponder()
}
else {
self.view.endEditing(true)
}
return true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
activeTextField = textField
scrollView.isScrollEnabled = true
}
func textFieldDidEndEditing(_ textField: UITextField) {
activeTextField = nil
scrollView.isScrollEnabled = false
}
}
Das hat für mich funktioniert:
func setupKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWasShown:"), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillBeHidden:"), name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown(aNotification:NSNotification) {
let info = aNotification.userInfo
let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
let kbSize = infoNSValue.CGRectValue().size
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.3)
var rect : CGRect = self.view.frame
rect.size.height -= kbSize.height
self.view.frame = rect
UIView.commitAnimations()
}
func keyboardWillBeHidden(aNotification:NSNotification) {
let info = aNotification.userInfo
let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
let kbSize = infoNSValue.CGRectValue().size
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.3)
var rect : CGRect = self.view.frame
rect.size.height += kbSize.height
self.view.frame = rect
UIView.commitAnimations()
}
Wenn sich das Textfeld am unteren Rand des Bildschirms befinden sollte, ist die magischste Lösung die folgende Überschreibung auf Ihrem Viewcontroller:
override var inputAccessoryView: UIView? {
return <yourTextField>
}
Wir können den Code für Swift 4.1 eingeben
let keyBoardSize = 80.0
func keyboardWillShow() {
if view.frame.Origin.y >= 0 {
viewMovedUp = true
}
else if view.frame.Origin.y < 0 {
viewMovedUp = false
}
}
func keyboardWillHide() {
if view.frame.Origin.y >= 0 {
viewMovedUp = true
}
else if view.frame.Origin.y < 0 {
viewMovedUp = false
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if sender.isEqual(mailTf) {
//move the main view, so that the keyboard does not hide it.
if view.frame.Origin.y >= 0 {
viewMovedUp = true
}
}
}
func setViewMovedUp(_ movedUp: Bool) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.3)
// if you want to slide up the view
let rect: CGRect = view.frame
if movedUp {
rect.Origin.y -= keyBoardSize
rect.size.height += keyBoardSize
}
else {
// revert back to the normal state.
rect.Origin.y += keyBoardSize
rect.size.height -= keyBoardSize
}
view.frame = rect
UIView.commitAnimations()
}
func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillHide), name: .UIKeyboardWillHide, object: nil)
}
func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
in (BOOL) textFieldShouldBeginEditing: (UITextField *) textField
if (textField.frame.Origin.y > self.view.frame.size.height - 216)
{
if (screenHeight>500)
scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 100);
else
scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 216);
CGPoint scrollPoint = CGPointMake(0.0,(textField.frame.Origin.y - (self.view.frame.size.height - 216 - textField.frame.size.height - 20)));
[scrollView setContentOffset:scrollPoint animated:YES];
}
[scrollView setScrollEnabled:YES];
wenn Sie Keyboard zurücktreten, müssen Sie den folgenden Code schreiben
scrollView.contentSize = CGSizeMake(0.0, 640);
CGPoint scrollPoint = CGPointMake(0.0,0.0);
[scrollView setContentOffset:scrollPoint animated:YES];
Für Swift Entwickler mit Swift 3 ist hier das Repo https://github.com/jamesrochabrun/KeyboardWillShow
import UIKit
class ViewController: UIViewController {
//1 Create a view that will hold your TEXTFIELD
let textField: UITextField = {
let tf = UITextField()
tf.translatesAutoresizingMaskIntoConstraints = false
tf.layer.borderColor = UIColor.darkGray.cgColor
tf.layer.borderWidth = 3.0
return tf
}()
//2 global variable that will hold the bottom constraint on changes
var textfieldBottomAnchor: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
//3 add the view to your controller
view.addSubview(textField)
textField.heightAnchor.constraint(equalToConstant: 80).isActive = true
textField.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
textField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
textfieldBottomAnchor = textField.bottomAnchor.constraint(equalTo: view.bottomAnchor)
textfieldBottomAnchor?.isActive = true
setUpKeyBoardObservers()
}
//4 Use NSnotificationCenter to monitor the keyboard updates
func setUpKeyBoardObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
//5 toggle the bottom layout global variable based on the keyboard's height
func handleKeyboardWillShow(notification: NSNotification) {
let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect
if let keyboardFrame = keyboardFrame {
textfieldBottomAnchor?.constant = -keyboardFrame.height
}
let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
if let keyboardDuration = keyboardDuration {
UIView.animate(withDuration: keyboardDuration, animations: {
self.view.layoutIfNeeded()
})
}
}
func handleKeyboardWillHide(notification: NSNotification) {
textfieldBottomAnchor?.constant = 0
let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
if let keyboardDuration = keyboardDuration {
UIView.animate(withDuration: keyboardDuration, animations: {
self.view.layoutIfNeeded()
})
}
}
//6 remove the observers
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
}
In iOS ist das Verschieben der Tastatur und das Zurücknehmen von Textfeldern in der App etwas verwirrend und Sie müssen einige Methoden für das gleiche . Implementieren. Außerdem müssen Sie das Delegieren in das Textfeld vornehmen und darauf achten jede Klasse, in der die Textfelder vorhanden sind.
Ich ziehe es vor, dieses Github-Steuerelement zu verwenden.
In dem Wir müssen nichts tun. - Ziehen Sie einfach die Drop-Control-Taste zu Ihrem Projekt und Build. - Es wird alles für Ihre App tun.
Vielen Dank
Vielleicht ist das nützlich.
Ich habe festgestellt, dass @DK_ die Lösung ist, mit der ich angefangen habe. Es wird jedoch davon ausgegangen, dass die scrollView die gesamte Ansicht abdeckt. Das war bei mir nicht der Fall. Ich wollte nur eine scrollView für den Fall, dass die Tastatur das untere Textfeld meines Anmeldebildschirms verdeckt. Daher hatte meine Inhaltsansicht dieselbe Größe wie meine Bildlaufansicht, die kleiner als die Hauptansicht war.
Landschaften waren auch nicht berücksichtigt, weshalb ich anfänglich in Schwierigkeiten geriet. Nachdem ich einige Tage damit herumgespielt habe, ist dies meine keyboardWasShown:
Methode.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
// A lot of the inspiration for this code came from http://stackoverflow.com/a/4837510/594602
CGFloat height = 0;
NSDictionary* info = [aNotification userInfo];
CGRect kbFrameRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect kbBoundsRect = [self.view convertRect:kbFrameRect fromView:nil]; // Convert frame from window to view coordinates.
CGRect scrollRect = scrollView.frame;
CGRect intersect = CGRectIntersection(kbBoundsRect, scrollRect);
if (!CGRectIsNull(intersect))
{
height = intersect.size.height;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
// Figure out what the view rectangle is for the scrollView
CGPoint contentOffset = scrollView.contentOffset;
CGRect visibleRect = CGRectOffset(scrollRect, contentOffset.x, contentOffset.y); // I'm not 100% sure if this is needed/right. My scrollView was always at the top in testing.
visibleRect.size.height -= height;
CGRect activeRect = activeField.frame;
if (!CGRectContainsRect(visibleRect, activeRect))
{
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
Ich hatte auch einige Schwierigkeiten, mit dem automatischen Layout zu arbeiten. Wenn die Layouts nicht korrekt erstellt wurden, wird der erwartete Bildlauf nicht ausgeführt. Eine Sache, die das Leben viel einfacher machte, war, alle Elemente, die gescrollt werden sollten, in einer einzigen Ansicht zu platzieren und diese als das einzige Element in der Scroll-Ansicht zu platzieren. Ich habe diese einzelne Ansicht die "Inhaltsansicht" genannt.
Ich denke, der Schlüssel war, dass die Inhaltsansicht eine festgelegte Breite und Höhe hatte. Dadurch konnte die Bildlaufansicht genau wissen, mit wie viel Inhalten sie umgehen musste. Dies geht etwas rückwärts von den üblichen Layouts. Normalerweise versuchen die Ansichten, so viel Platz wie möglich einzunehmen. Mit dem Inhalt einer Bildlaufansicht versuchen Sie, die Ansicht so weit wie möglich einzuschränken. In der Inhaltsansicht können Sie dem ein Ende setzen. Also gab ich mir eine Höhe von 248 und verwendete die Standard-Bildschirmbreite von 320 als meine Breite.
Die Layouts, die letztendlich für mich funktionierten, waren folgende:
Horizontal Space - View - Scroll View
(0)Vertical Space - View - Scroll View
(0)Horizontal Space - Scroll View - View
(0)Height - (248) - Scroll View
Vertical Space - View - Scroll View
(0)Vertical Space - Scroll View - View
(0)Horizontal Space - View - Scroll View
(0)Horizontal Space - Scroll View - View
(0)Height - (248) - View
Width - (320) - View
Sie können dieses einfache Git-Repository verwenden: https://github.com/hackiftekhar/IQKeyboardManager
Dies ist eine Bibliothek, die das Verschieben von Feldern automatisch verwaltet.
Laut ihrer Readme-Datei ist die Integration sehr einfach:
ohne dass Sie einen Code eingeben müssen und keine weiteren Einstellungen erforderlich sind. Um IQKeyboardManager verwenden zu können, müssen Sie einfach Quelldateien zu Ihrem Projekt hinzufügen.
Dies ist zwar eine sehr gute Kontrolle, in manchen Fällen führt dies jedoch zu Konflikten, wie bei den View-Controllern mit Scroll-Ansicht. Manchmal ändert sich die Inhaltsgröße. Sie können es trotzdem versuchen und es je nach Ihren Anforderungen ausprobieren. Vielleicht könnten Sie tun, was ich vermisst habe.
siehe UICatalogView
Beispiele für iPhone live und geladen
ich hatte ein Problem mit dem Zurücksetzen in die Standard-Hauptansicht, während das Textfeld geändert wurde oder dessen Inhalt bearbeitet wurde (z. B. Telefon-Textfeld und Hinzufügen von "-" - Zeichen, und Ansicht geht zurück auf Textfelder) Das Ändern von Bedingungen konstant, nicht die Frame-Größe oder Position in Benachrichtigungs-Delegaten-Funktionen, wie folgt:
P.S. Ich verwende Scrollview nicht einfach nur nach oben, aber es sollte ähnlich funktionieren
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if !keyboardIsShown{
self.infoViewTopConstraint.constant -= keyboardSize.height
self.infoViewBottomConstraint.constant += keyboardSize.height
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
keyboardIsShown = true
}
}
func keyboardWillHide(notification: NSNotification) {
if keyboardIsShown {
self.infoViewTopConstraint.constant += keyboardSize.height
self.infoViewBottomConstraint.constant -= keyboardSize.height
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
keyboardIsShown = false
}
Diese Frage hat bereits viele Antworten, von denen einige sagten, dass sie die Scroll-Ansicht verwenden, einige sagten, dass sie eine dritte lib verwenden.
Aber für mich sollte die Ideenlösung UITableViewController
mit statischen Zellen sein.
Sie trennen Ihre Benutzeroberfläche in mehrere Teile und legen diese nacheinander in die tableViewCells ein. Dann brauchen Sie sich keine Sorgen mehr um die Tastatur zu machen. TableViewController verwaltet es automatisch für Sie.
Es kann ein wenig schwierig sein, die Auffüllung, den Rand und die Zellenhöhe zu berechnen, aber wenn Ihre Berechnungen in Ordnung sind, ist es einfach.
Ich verwende Swift und Auto Layout (kann die vorherige Swift-Antwort jedoch nicht kommentieren); So mache ich das ohne Scrollen:
Ich gestalte mein Formular in IB mit vertikalen Einschränkungen zwischen den Feldern, um sie voneinander zu trennen. Ich füge der Containeransicht eine vertikale Einschränkung aus dem obersten Feld hinzu und erstelle einen Auslass dazu (topSpaceForFormConstraint im nachstehenden Code). Alles, was Sie brauchen, ist, diese Einschränkung zu aktualisieren, was ich in einem Animationsblock für eine Nice-Soft-Bewegung mache. Die Höhenüberprüfung ist natürlich optional. In diesem Fall musste ich sie nur für die kleinste Bildschirmgröße durchführen.
Dies kann mit einer der üblichen textFieldDidBeginEditing- oder keyboardWillShow-Methoden aufgerufen werden.
func setFormHeight(top: CGFloat)
{
let height = UIScreen.mainScreen().bounds.size.height
// restore text input fields for iPhone 4/4s
if (height < 568) {
UIView.animateWithDuration(0.2, delay: 0.0, options: nil, animations: {
self.topSpaceForFormConstraint.constant = top
self.view.layoutIfNeeded()
}, completion: nil)
}
}
Ich habe diese Möglichkeit hier nicht gesehen, also füge ich sie hinzu, da ich die Methoden in den Antworten ausprobiert habe, aber Stunden später festgestellt habe, dass es eine Menge gibt. Einfacherer Weg in XCode 5 unter iOS6/7: Verwenden Sie NSLayoutConstraints.
Siehe: Autolayout-Einschränkung - Tastatur
Hier ist mein Code:
.m Datei:
// Called when the UIKeyboardWillShowNotification is sent.
- (void)keyboardWillBeShown:(NSNotification*)aNotification
{
NSLog(@"keyboardWillBeShown:");
[self.PhoneNumberLabelOutlet setHidden:TRUE];
CGFloat heightOfLabel = self.PhoneNumberLabelOutlet.frame.size.height;
for( NSLayoutConstraint* thisConstraint in self.topElementsVerticalDistanceFromTopLayoutConstraint ) {
thisConstraint.constant -= heightOfLabel;
}
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGFloat oldConstant = [self.SignInYConstraint constant];
self.SignInYConstraint.constant = oldConstant + kbSize.height;
[self.view setNeedsUpdateConstraints];
NSTimeInterval duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration:duration animations:^{
[self.view layoutIfNeeded];
}];
}
.h Datei:
#import <UIKit/UIKit.h>
@interface SignInViewController : UIViewController {
UITextField* _activeField;
}
- (void)signInCallback:(NSObject*)object;
@property (weak, nonatomic) IBOutlet UILabel *PhoneNumberLabelOutlet;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *ActivityIndicatorOutlet;
@property (weak, nonatomic) IBOutlet UITextField *UserIDTextfieldOutlet;
@property (weak, nonatomic) IBOutlet UITextField *PasswordTextfieldOutlet;
@property (weak, nonatomic) IBOutlet UIButton *SignInButton;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *SignInYConstraint;
@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *topElementsVerticalDistanceFromTopLayoutConstraint;
@end
Swift 5
in viewDidLoad oder viewDidAppear add addKeyboardObservers -Methode.
fileprivate func addKeyboardObservers(){
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
fileprivate func removeKeyboardObservers(){
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
}
@objc fileprivate func keyboardWillHide(_ notification: Notification){
if (window == nil) {return}
guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}
scrollView.contentInset.bottom = .zero
}
@objc fileprivate func keyboardWillShow(_ notification: Notification){
if (window == nil) {return}
if UIApplication.shared.applicationState != .active { return }
// keyboard height
guard let height = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height else {return}
// keyboard present animation duration
guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}
scrollView.contentInset.bottom = height
}
vergiss nicht, Beobachter beim Deinitieren zu entfernen oder zu verschwinden
self.removeKeyboardObservers()
ich bin ein bisschen spät dran. Sie sollten scrollView auf Ihrem viewController hinzufügen.
Sie müssen unter 2 Methode implementieren.
TextField-Delegatmethode.
- (void)textFieldDidBeginEditing:(UIView *)textField {
[self scrollViewForTextField:reEnterPINTextField];
}
Rufen Sie dann die folgende Methode in Delegate auf.
- (void)scrollViewForTextField:(UIView *)textField {
NSInteger keyboardHeight = KEYBOARD_HEIGHT;
if ([textField UITextField.class]) {
keyboardHeight += ((UITextField *)textField).keyboardControl.activeField.inputAccessoryView.frame.size.height;
}
CGRect screenFrame = [UIScreen mainScreen].bounds;
CGRect aRect = (CGRect){0, 0, screenFrame.size.width, screenFrame.size.height - ([UIApplication sharedApplication].statusBarHidden ? 0 : [UIApplication sharedApplication].statusBarFrame.size.height)};
aRect.size.height -= keyboardHeight;
CGPoint relativeOrigin = [UIView getOriginRelativeToScreenBounds:textField];
CGPoint bottomPointOfTextField = CGPointMake(relativeOrigin.x, relativeOrigin.y + textField.frame.size.height);
if (!CGRectContainsPoint(aRect, bottomPointOfTextField) ) {
CGPoint scrollPoint = CGPointMake(0.0, bottomPointOfTextField.y -aRect.size.height);
[contentSlidingView setContentOffset:scrollPoint animated:YES];
}
}
Füge meine 5 Cent hinzu :)
Ich ziehe immer vor, tableView für inputTextField oder scrollView zu verwenden. In Kombination mit Benachrichtigungen können Sie dieses Verhalten problemlos verwalten. (Hinweis: Wenn Sie statische Zellen in tableView verwenden, wird dieses Verhalten automatisch für Sie verwaltet.)
// MARK: - Notifications
fileprivate func registerNotificaitions() {
NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillAppear(_:)),
name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillDisappear),
name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
fileprivate func unregisterNotifications() {
NotificationCenter.default.removeObserver(self)
}
@objc fileprivate func keyboardWillAppear(_ notification: Notification) {
if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
view.layoutIfNeeded()
UIView.animate(withDuration: 0.3, animations: {
let heightInset = keyboardHeight - self.addDeviceButton.frame.height
self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: heightInset, right: 0)
self.view.layoutIfNeeded()
}, completion: nil)
}
}
@objc fileprivate func keyboardWillDisappear() {
view.layoutIfNeeded()
UIView.animate(withDuration: 0.3, animations: {
self.tableView.contentInset = UIEdgeInsets.zero
self.view.layoutIfNeeded()
}, completion: nil)
}