在iOS9上编辑UITextField时上移键盘

时间:2015-09-17 13:17:06

标签: ios objective-c uitextfield

为了让我的键盘在我的iOS应用程序中向上移动以发现UITextField,我曾经在iOS7和8上实现了这个答案:https://stackoverflow.com/a/6908258/3855618,它现在已经完美运行了。但是在iOS 9.1上,它不再起作用了。

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

了解自iOS9和iOS 9.1以来发生了多大变化?

7 个答案:

答案 0 :(得分:36)

不推荐您链接的答案。您不应直接设置视图控制器视图的框架,尤其是在使用自动布局时。您应该将滚动视图作为子视图添加到视图中,而不是更改视图的框架,并在显示或隐藏键盘时调整内容插入。

来自官方苹果doc

  

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

     

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

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

答案 1 :(得分:8)

代码零行

没有黑客,kludges,变通方法和听众。

自iOS时代开始以来,一直在问这个问题。 StackOverflow上的答案没有超过2次iOS迭代。这是正确的,因为 UIKit 不断从脚下变换。存在设计而不是实现解决这个古老问题的方法。使用UITableViewController

使用UITableViewController

UITableViewUITableViewController管理时,会自动为您管理滚动。永远不要再修补UIKeyboardWillShowNotification。只需创建静态或动态UITableViewCells来布局界面,根据需要添加UITextViewUITextField;仅仅成为第一响应者将滚动正确的位置。

  

@availability(iOS,介绍= 2.0)

UITableViewController

备注

  1. 适用于自2.0以来的所有iOS
  2. 引用:«浪费时间优化不良算法;选择一个更好的»
  3. 请参阅https://stackoverflow.com/a/32390936/218152

答案 2 :(得分:3)

我们需要从通知中取出键盘框架。获取scrollView,tableView等参考时将视图的低边框转换为窗口坐标。当确定我们的视图覆盖多少键盘时,如果差值大于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];
}

答案 3 :(得分:1)

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

答案 4 :(得分:1)

我通常会听取键盘通知并根据布局限制进行更改。有关更多详细信息和示例项目,请参阅我的其他answer

答案 5 :(得分:1)

尝试使用我之前项目中使用的代码:

- (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];
}

答案 6 :(得分:1)

我按照@Istvan的文档到苹果网站,并且有很多东西丢失以使其工作:
1.将.h文档设置为&lt; UITextFieldDelegate&gt; (能够使用“activefield”)
2.在viewDidLoad中,将委托设置为您的UITextfields,并将您的scrollview内容的高度设置为更大的高度(在我的情况下,我已经设置了500多个):

join_df.write.json("join.json")
join_json = sqlContext.read.parquet("join.json")
join_json.count()

现在一切正常......