iPhone键盘覆盖UITextField
我有一个应用程序,在界面生成器中 ,我设置了一个UIView
,在视图底部附近有一个文本字段。 当我运行应用程序并尝试在该字段中input文本时,键盘向上滑动,所以我看不到我正在input的内容,直到我再次隐藏键盘。
有没有其他人遇到这个问题,并find一个好的方法来解决这个问题,而不使父视图滚动或移动屏幕上的文本字段?
通常的解决方法是用animation滑动字段(以及其上的所有内容),然后在完成时退回。 您可能需要将文本字段和一些其他项目放到另一个视图中,并将视图作为一个单元滑动。 (我把这些东西称为“板块”,就像“板块”一样,但这只是我)。 但是,如果你不需要花哨的话,这里就是一般的想法。
- (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]; }
这对我滑动uitextfields工作奇迹
特别是它具有根据文本字段的位置计算滑动animation距离的好处。
IQKeyboardManager为您做NO LINE CODE ,只需将相关源文件拖放到工程中即可。 IQKeyboardManager还支持设备方向 , 自动UIToolbarpipe理 , keyboardDistanceFromTextField以及远远超出您的想象。
这里是控制stream程图:
第1步: –在单例类中添加了UITextField
, UITextView
和UIKeyboard
全局通知。 我把它叫做IQKeyboardManager 。
第2 UIKeyboardWillShowNotification
: –如果findUIKeyboardWillShowNotification
, UITextFieldTextDidBeginEditingNotification
或UITextViewTextDidBeginEditingNotification
通知,则尝试从UIWindow.rootViewController
层次结构中获取topMostViewController
实例。 为了正确地发现它的UITextField
/ UITextView
,需要调整topMostViewController.view
的框架。
第3步: –计算预计的移动距离topMostViewController.view
相对于第一个响应的UITextField
/ UITextView
。
第四步: –根据预期的移动距离向上/向下移动topMostViewController.view.frame
。
第5步: –如果findUIKeyboardWillHideNotification
, UITextFieldTextDidEndEditingNotification
或UITextViewTextDidEndEditingNotification
通知,则再次尝试从UIWindow.rootViewController
层次结构中获取topMostViewController
实例。
topMostViewController.view
步: –计算topMostViewController.view
需要恢复到原始位置的干扰距离。
第7步: –根据受干扰的距离,恢复topMostViewController.view.frame
。
步骤8:在应用程序加载时实例化单例IQKeyboardManager类实例,所以应用程序中的每个UITextField
/ UITextView
将根据预期的移动距离自动调整。
就这样
为了扩展Amagrammer的答案,下面是一个示例类:
LoginViewController.h
@interface LoginViewController : UIViewController <UITextFieldDelegate> { } @property (nonatomic, retain) IBOutlet UITextField *emailTextField; @property (nonatomic, retain) IBOutlet UITextField *passwordTextField;
注意我们正在执行“UITextFieldDelegate”
LoginViewController.m
@implementation LoginViewController @synthesize emailTextField=_emailTextField; @synthesize passwordTextField=_passwordTextField; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { //Register to receive an update when the app goes into the backround //It will call our "appEnteredBackground method [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnteredBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; } return self; } - (void) animateTextField: (UITextField*) textField up: (BOOL) up { const int movementDistance = 80; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? -movementDistance : movementDistance); [UIView beginAnimations: @"anim" context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; } - (void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField: textField up: YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField: textField up: NO]; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return YES; } //This is called when the app goes into the background. //We must reset the responder because animations will not be saved - (void)appEnteredBackground{ [self.emailTextField resignFirstResponder]; [self.passwordTextField resignFirstResponder]; }
官方解决scheme如何: 移动位于键盘下的内容
调整您的内容通常涉及临时调整一个或多个视图的大小,并定位它们,以使文本对象保持可见。 用键盘pipe理文本对象最简单的方法就是将它们embedded到UIScrollView对象(或者它的一个子类如UITableView)中。 显示键盘时,您只需重置滚动视图的内容区域,然后将所需的文本对象滚动到位置即可。 因此,为了响应UIKeyboardDidShowNotification,您的处理程序方法将执行以下操作:
- 获取键盘的大小。
- 通过键盘高度调整滚动视图的底部内容插入。
- 将目标文本字段滚动到视图中。
// Call this method somewhere in your view controller setup code. - (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } // Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWasShown:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0); scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; // If active text field is hidden by keyboard, scroll it so it's visible // Your app might not need or want this behavior. CGRect aRect = self.view.frame; aRect.size.height -= kbSize.height; if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) { [self.scrollView scrollRectToVisible:activeField.frame animated:YES]; } } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; }
我在UITableView
textField单元格面临同样的问题。 我通过执行下面的方法来解决这个问题来听键盘通知。
观察员在这里的通知:
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
通过使用下面的函数来处理这些通知:
(void)keyboardWasShown:(NSNotification*)aNotification (void)keyboardWillBeHidden:(NSNotification*)aNotification
看一下这个。 没有麻烦你。
这个解决scheme非常整齐。 所有你需要做的就是添加你的文本字段在UIScrollView
,并将其类改为TPKeyboardAvoidingScollView
,如果你正在使用故事板。 滚动视图以这样的方式扩展,即当键盘可见时,它将检测到并且将在合理的距离上在键盘上移动。 这是完美的解决scheme,因为它独立于你的UIViewController
。 在上面提到的课程中,每一个必要的事情都是完成的。 感谢迈克尔泰森等。
TPKeyboardAvoiding
下面是Amagrammer的答案的一个迅速版本。 此外,使用UIKeyboardWillShowNotification事件的变化,因为我需要知道键盘的大小,然后移动视图。
var keyboardHeight:CGFloat = 0 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChange:", name: UIKeyboardWillShowNotification, object: nil) } func textFieldDidBeginEditing(textField: UITextField) { //keyboardWillChange (below) is used instead of textFieldDidBeginEditing because textFieldDidBeginEditing //is called before the UIKeyboardWillShowNotification necessary to determine the keyboard height. } func textFieldDidEndEditing(textField: UITextField) { animateTextField(false) } func animateTextField(textFieldUp:Bool) { let movementDistance:CGFloat = keyboardHeight let movementDuration = 0.3 let movement:CGFloat = (textFieldUp ? -movementDistance : movementDistance) UIView.beginAnimations("anim", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration) self.view.frame = CGRectOffset(self.view.frame, 0, movement) UIView.commitAnimations() } func keyboardWillChange(notification:NSNotification) { let keyboardRect:CGRect = ((notification.userInfo![UIKeyboardFrameEndUserInfoKey])?.CGRectValue)! keyboardHeight = keyboardRect.height animateTextField(true) }
有一个伟大的演练编辑文本框没有模糊 (现在链接死了,这里是一个Wayback链接: https ://web.archive.org/web/20091123074029/http: /acts-as-geek.blogspot.com/2009/ 11 / editing-textfields-without-obscuring.html )。 它显示了如何将现有的UIView
移动到UIScrollView
,并在出现键盘时自动滚动它。
当UIScrollView
下面有控件(比如一个UITabBar
)时,我已经更新了一点来计算UIScrollView
的正确高度。 查看post更新uiview 。
这是一个使用Xcode5,iOS7的解决scheme:
使用UITextfieldDelegate和animation块。
这几乎是ViewController的所有代码,但是我想包含那些对代理模式还是有点不熟悉的委托代码(比如我)。 我还包括隐藏键盘的代码,当你离开textview。
您可以将视图(button,文本框等)移动到您想要的位置(+100,然后在-100)。
@interface ViewController () <UITextFieldDelegate> @property (strong, nonatomic) IBOutlet UITextField *MyTextField; @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.MyTextField.delegate = self; } - (void)textFieldDidBeginEditing:(UITextField *)textField { NSLog(@"text began editing"); CGPoint MyPoint = self.MyTextField.center; [UIView animateWithDuration:0.3 animations:^{ self.MyTextField.center = CGPointMake(MyPoint.x, MyPoint.y - 100); }]; } - (void)textFieldDidEndEditing:(UITextField *)textField { NSLog(@"text ENDED editing"); CGPoint MyPoint = self.MyTextField.center; [UIView animateWithDuration:0.3 animations:^{ self.MyTextField.center = CGPointMake(MyPoint.x, MyPoint.y + 100); }]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; }
我想一种方法是将整个视图的位置从(x,y)移动到(x,y-keybaardHeight),当文本框被点击并放回时,键盘被解散,可能会看起来有点奇怪出现了(也许它不会坏,如果你animation)。
- (void)textFieldDidBeginEditing:(UITextField *)textField { CGRect frame=self.view.frame; frame.origin=CGPointMake(x...//set point here self.view.frame=frame; }
除了Amagrammer的解决scheme之外,如果您在纵向模式下使用cocos2d,请更改以下行:
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
对此:
[CCDirector sharedDirector].openGLView.frame = CGRectOffset([CCDirector sharedDirector].openGLView.frame, movement, 0);
如果您在横向模式下使用cocos2d,请进行上述更改并在textFieldDidBeginEditing:
和textFieldDidEndEditing:
切换textFieldDidEndEditing:
- (void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField:textField up:NO]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField:textField up:YES]; }
我有同样的问题,发现GTKeyboardHelper是一个简单的出路。
将框架拖放到项目中后,包含头文件。 下载并打开示例项目,然后将“键盘帮助程序”对象从xib中的对象部分拖到项目界面生成器中的对象部分。
将所有视图拖放到“键盘帮助器”的子项目中。
你怎么处理的情况下,键盘和框架已resize与animation和滚动,所以没有覆盖的文本字段,从那里,当我select另一个文本字段(仍在编辑第一个文本字段)如何不再播放animation和如果有必要进一步滚动一下? 这个问题是在不需要的时候重放整个animation。 谢谢
拖放我在项目中使用的框架。 当您轻触第一响应者之外或滚动时支持自动解除。
GTKeyboardHelper
请看我的评论:
iPhone – 键盘隐藏TextField
只需根据需要上下滑动视图即可:
- (void)textFieldDidEndEditing:(UITextField *)textField { self.currentTextField = nil; [self animateTextField: textField up: NO]; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { [self.currentTextField resignFirstResponder]; return YES; } - (void) animateTextField:(UITextField*) textField up:(BOOL)up { const int movementDistance = 80; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? -movementDistance : movementDistance); [UIView animateWithDuration:movementDuration animations:^{ self.view.frame = CGRectOffset(self.view.frame, 0, movement); }]; }
不要忘记将self
设置为UITextFieldDelegate
,并将其设置为实际的textField delegate
。
(感谢Ammagrammer,这只是一个使用animation块的简短答案)
如果你想要的话,我还有别的东西。 这里的要点是,你想在你正在编辑的文本字段上设置你的UIView的中心。
在此之前,你必须保存你的INITIAL_CENTER ,作为CGPoint ,从self.view.center和你的INITIAL_VIEW作为CGRect从self.view.frame在一个const属性。
你可以创build一个像这样的方法:
- (void) centerOn: (CGRect) fieldFrame { // Set up the center by taking the original view center CGPoint center = CGPointMake(INITIAL_CENTER.x, INITIAL_CENTER.y - ((fieldFrame.origin.y + fieldFrame.size.height/2) - INITIAL_CENTER.y)); [UIView beginAnimations:@"centerViewOnField" context:nil]; [UIView setAnimationDuration:0.50]; if (CGRectEqualToRect(fieldFrame,INITIAL_VIEW)) { self.view.frame = INITIAL_VIEW; [self.view setCenter:INITIAL_CENTER]; } else { [self.view setCenter:center]; } [UIView commitAnimations]; }
然后,在你的UITextFieldDelegate上 ,你必须在下面的方法中调用centerOn:(CGRect) :
textFieldDidBeginEditing:(UITextField *) ,作为一个参数,你想要居中的文本框的框架。
你必须在你的事件处理程序中调用它,closures键盘,
textFieldDidEndEditing:(UITextField *)可以做到这一点,将INITIAL_VIEW作为centerOn:(CGRect)的参数。
我相信iOS的更新版本(6.1+,甚至更早),底层视图,至less对于UITableView,popup键盘时会自动收缩。 所以你只需要在该视图中显示文本字段。 在init
:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
然后:
- (void)keyboardWasShown:(NSNotification*)notification { // Scroll the text field into view so it's not under the keyboard. CGRect rect = [self.tableView convertRect:inputView.bounds fromView:inputView]; [self.tableView scrollRectToVisible:rect animated:YES]; }
https://github.com/ZulwiyozaPutra/Shift-Keyboard-Example我希望这个解决scheme有帮助。; 他们都是斯威夫特写的。
// // ViewController.swift // Shift Keyboard Example // // Created by Zulwiyoza Putra on 11/23/16. // Copyright © 2016 Zulwiyoza Putra. All rights reserved. // import UIKit class ViewController: UIViewController, UITextFieldDelegate { //connecting textfield from storyboard @IBOutlet weak var textField: UITextField! override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) subscribeToKeyboardNotifications() } override func viewDidAppear(_ animated: Bool) { self.textField.delegate = self } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) unsubscribeFromKeyboardNotifications() } //Hide keyboard after finished editing func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } //Setup view before keyboard appeared func keyboardWillAppear(_ notification:Notification) { view.frame.origin.y = 0 - getKeyboardHeight(notification) } //Setup view before keyboard disappeared func keyboardWillDisappear(_ notification: Notification) { view.frame.origin.y = 0 } //Getting keyboard height func getKeyboardHeight(_ notification:Notification) -> CGFloat { let userInfo = notification.userInfo let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue // of CGRect return keyboardSize.cgRectValue.height } //Subscribing to notifications to execute functions func subscribeToKeyboardNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear(_:)), name: .UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear(_:)), name: .UIKeyboardWillHide, object: nil) } //Unsubscribing from notifications func unsubscribeFromKeyboardNotifications() { NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil) } }