我有一个应用程序,在Interface Builder中,我设置了一个UIView
在视图底部附近有文本字段的应用程序.当我运行应用程序并尝试在该字段中输入文本时,键盘会向上滑动到字段上方,所以在我再次隐藏键盘之前,我无法看到我正在键入的内容.
有没有其他人遇到这个问题并找到一个很好的方法来解决它,既没有使父视图可滚动或移动文本字段更远的屏幕?
通常的解决方案是用动画将场(以及它上面的所有东西)向上滑动,然后在完成后退回.您可能需要将文本字段和其他一些项目放入另一个视图中,并将视图作为一个单元滑动.(我将这些东西称为"板块",如"构造板块",但那只是我).但如果你不需要花哨的话,这就是一般的想法.
- (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的奇迹
特别地,它具有根据文本字段的位置计算幻灯片动画距离的益处.
IQKeyboardManager通过NO LINE OF CODE为您完成此操作,只需将相关的源文件拖放到项目中即可.IQKeyboardManager还支持设备方向,自动UIToolbar管理,keyboardDistanceFromTextField以及比您想象的更多.
这是控制流程图:
第一步: -增加了全球的通知UITextField
,UITextView
和UIKeyboard
在一个单独的类.我叫它IQKeyboardManager.
第二步: -如果找到UIKeyboardWillShowNotification
,UITextFieldTextDidBeginEditingNotification
或UITextViewTextDidBeginEditingNotification
通知,然后尝试获得topMostViewController
从实例UIWindow.rootViewController
层次结构.为了正确地揭开它UITextField
/ UITextView
它,topMostViewController.view
需要调整框架.
步骤3: -计算topMostViewController.view
相对于第一响应的预期移动距离UITextField
/ UITextView
.
第四步: -感动topMostViewController.view.frame
向上/向下按预期的移动距离.
第五步: -如果找到UIKeyboardWillHideNotification
,UITextFieldTextDidEndEditingNotification
或UITextViewTextDidEndEditingNotification
通知,然后再次尝试获得topMostViewController
从实例UIWindow.rootViewController
层次结构.
步骤6: -计算出的干扰距离topMostViewController.view
需要恢复到原始位置.
步骤7: -topMostViewController.view.frame
根据受干扰的距离恢复.
步骤8: -应用程序加载时实例化的单例IQKeyboardManager类实例,因此应用程序中的每个UITextField
/ UITextView
都将根据预期的移动距离自动调整.
就这样
我在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
要扩展Amagrammer的答案,这是一个示例类:
LoginViewController.h
@interface LoginViewController : UIViewController{ } @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]; }
官方解决方案如何:移动位于键盘下的内容
调整内容通常涉及暂时调整一个或多个视图的大小并对其进行定位,以使文本对象保持可见.使用键盘管理文本对象的最简单方法是将它们嵌入到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; }
看一下这个.没有麻烦给你.
这个解决方案很整洁.如果您使用的是故事板,那么您所要做的就是在a中添加文本字段UIScrollView
并将其更改为类TPKeyboardAvoidingScollView
.滚动视图以这样的方式扩展,即它将检测键盘何时可见并且将在合理距离处将其自身移动到键盘上方.这是完美的解决方案,因为它独立于您的UIViewController
.每个必要的事情都在上面提到的课程中完成.谢谢Michael Tyson等人.
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) }