在iOS9上编辑UITextField时上移键盘

对于我的键盘来移动到我的iOS应用程序中发现UITextField ,我用来实现这个答案:iOS7和8上的https://stackoverflow.com/a/6908258/3855618 ,它现在完美的工作。 但是,在iOS 9.1上,它不再工作。

为了更准确,即使背景视图向上移动, UITextField也不会。

自从iOS9和iOS9.1以来有什么变化了吗?

不build议您链接的答案。 您不应该直接设置视图控制器视图的框架,特别是如果您正在使用自动布局。 您应该将scrollview作为子视图添加到视图,而不是更改视图的框架,并在显示或隐藏键盘时调整插入的内容。

从官方的苹果文档 :

当系统要求显示键盘时,系统会从屏幕底部滑入,并将其放在应用程序的内容上。 由于它位于内容之上,因此可以将键盘放置在用户想要编辑的文本对象的顶部。 发生这种情况时,您必须调整您的内容,以便目标对象保持可见。

调整您的内容通常涉及临时调整一个或多个视图的大小,并定位它们,以使文本对象保持可见。 用键盘pipe理文本对象最简单的方法就是将它们embedded到UIScrollView对象(或者它的一个子类如UITableView)中。 显示键盘时,您只需重置滚动视图的内容区域,然后将所需的文本对象滚动到位置即可。 因此,为了响应UIKeyboardDidShowNotification,您的处理程序方法将执行以下操作:

  1. 获取键盘的大小。
  2. 通过键盘高度调整滚动视图的底部内容插入。
  3. 将目标文本字段滚动到视图中。
  // 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; } 

代码的零线

没有黑客,诡计,解决方法和听众。

自从iOS时代开始以来,这个问题一直在被问及。 StackOverflow没有答案幸存了超过2个iOS迭代。 正确的是,因为UIKit不断从脚下改变。 存在一个devise而不是解决这个古老的问题的解决scheme。 使用UITableViewController

使用UITableViewController

UITableViewUITableViewpipe理时,滚动会自动为您pipe理。 切勿再次修改UIKeyboardWillShowNotification 。 只需创build静态或dynamicUITableViewCells来布局你的接口,根据需要添加UITextViewUITextField ; 只是成为第一响应者将滚动适当的位置。

@availability(iOS,引入= 2.0)

的UITableViewController

笔记

  1. 适用于2.0以来的所有iOS
  2. Quote: “浪费没有时间优化一个可怜的algorithm; select一个更好的»
  3. 请参阅https://stackoverflow.com/a/32390936/218152

我们需要通知键盘框架。 当获取scrollView,tableView等的引用时,将视图的低边框转换为窗口的坐标。 当确定多less键盘覆盖我们的视图,如果差异大于0,我们可以在下面添加插入。 试试这个代码:

 - (void)subscribeKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)unsubscribeKeyboardNotifications { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } - (void)keyboardWillShow:(NSNotification *)aNotification { CGRect keyBoardFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; UIWindow *keyWindow = [[[UIApplication sharedApplication] delegate] window]; UIScrollView *someScrollView = ...... CGPoint tableViewBottomPoint = CGPointMake(0, CGRectGetMaxY([someScrollView bounds])); CGPoint convertedTableViewBottomPoint = [someScrollView convertPoint:tableViewBottomPoint toView:keyWindow]; CGFloat keyboardOverlappedSpaceHeight = convertedTableViewBottomPoint.y - keyBoardFrame.origin.y; if (keyboardOverlappedSpaceHeight > 0) { UIEdgeInsets tableViewInsets = UIEdgeInsetsMake(0, 0, keyboardOverlappedSpaceHeight, 0); [someScrollView setContentInset:tableViewInsets]; } } - (void)keyboardWillHide:(NSNotification *)aNotification { UIEdgeInsets tableViewInsets = UIEdgeInsetsZero; UIScrollView *someScrollView = ...... [someScrollView setContentInset:tableViewInsets]; } 

在UIScrollView上添加所有UITextField并使用TPKeyboardAvoiding

我通常听键盘通知,并根据布局约束的变化。 看到我的其他答案更多的细节和示例项目。

试试我在以前的项目中使用过的代码:

 - (void)textFieldDidBeginEditing:(UITextField *)textField { [self didBeginEditingIn:textField]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self didEndEditing]; } 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+100; static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162+100; - (void)didBeginEditingIn:(UIView *)view { CGRect textFieldRect = [self.view.window convertRect:view.bounds fromView:view]; 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)didEndEditing { 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]; } 

我跟着从@Istvan的文件到苹果网站,有很多东西失踪,使其工作:
1.将你的.h文件设置为<UITextFieldDelegate>(能够使用“activefield”)
2.在viewDidLoad中,将代表设置为你的UITextfields,并设置更高的滚动视图内容的高度(在我的情况下,我已经设置了500多):

 CGRect screenRect = [[UIScreen mainScreen] bounds]; CGFloat screenWidth = screenRect.size.width; CGFloat screenHeight = screenRect.size.height + 500; _scrollView.contentSize = CGSizeMake(screenWidth, screenHeight); 

现在这一切正在工作…