在iOS7中键盘出现时调整UITextView的大小

时间:2013-10-07 15:58:22

标签: objective-c ios7

这个问题曾被问过几次,但我真的无法找到答案......

在iOS6中,每当键盘出现时,我都会使用以下内容调整UITextView的大小。在iOS7下,行为不是应该的(在我的情况下,似乎没有任何东西正在调整大小)。我怀疑原因是iOS7的自动布局/约束行为。有什么建议? (" notePad"是我的UITextView)?

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    //NSLog(@"KeyboardSize: %f.%f", kbSize.width, kbSize.height);

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, (kbSize.width > kbSize.height ? 
    kbSize.height : kbSize.width), 0);
    self.notePad.contentInset = contentInsets;
    self.notePad.scrollIndicatorInsets = contentInsets;
}

6 个答案:

答案 0 :(得分:15)

如果您在视图中使用自动布局,则以下方法可能会对您有所帮助。

首先为底部布局指南约束定义IBOutlet并与storyboard元素链接。

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst;

第二次添加键盘通知的观察者。

- (void)observeKeyboard {
    [[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 {
    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];
    }];
}

此方法支持方向更改和不同的键盘大小。希望它有所帮助。

答案 1 :(得分:4)

您的代码在逻辑上是正确的。当键盘出现时,您几乎不应该使用scrollview行为更改对象的框架,但是您应该只更改insets。 插件应相对于当前版本更改,因为iOS7负责调整导航栏。如果你提供一个新的插图可能你会破坏UI中的东西。 你的代码在iOS7上被破坏了两个主要原因:

  1. 您必须将自动布局约束添加到textview容器。 (可能你的文字视图比你想象的要大)
  2. 你不应该以绝对的方式改变插图。
  3. 以下是正确配置文本视图的步骤

    • 在xib(或故事板)中,向容器的顶部,左侧,右侧,底部添加约束(在我的情况下为{0,0,0,0},如下所示

    Autolayout constraint

    • 注册键盘通知

      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
      
      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
      
    • keyboardWillShowkeyboardWillHide中,不要更改框架,而是将插图相对于现有框架更改。

      - (void)keyboardWillShow:(NSNotification *)notification
      {
          // Take frame with key: UIKeyboardFrameEndUserInfoKey because we want the final frame not the begin one
          NSValue *keyboardFrameValue = [notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
          CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
      
          UIEdgeInsets contentInsets = self.textView.contentInset;
          contentInsets.bottom = CGRectGetHeight(keyboardFrame);
      
          self.textView.contentInset = contentInsets;
          self.textView.scrollIndicatorInsets = contentInsets;
      }
      
      - (void)keyboardWillHide:(NSNotification *)notification
      {
          UIEdgeInsets contentInsets = self.textView.contentInset;
          contentInsets.bottom = .0;
      
          self.textView.contentInset = contentInsets;
          self.textView.scrollIndicatorInsets = contentInsets;
      }
      
      • 然后记得删除观察员

答案 2 :(得分:3)

@BoranA有正确的答案,但需要调整所有键盘的全部功能。

请遵循以下代码:

将以下内容附加到Vertical Space - Bottom Layout Guide - TextField

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst;

第二次添加键盘通知的观察者。

- (void)observeKeyboard {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

将此添加到viewDidLoad

[self observeKeyboard]; 

最后处理键盘更改的方法。

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

答案 3 :(得分:1)

我发现我必须拨打[self layoutIfNeeded]才能让我的插图生效。

我的键盘通知方法如下所示(我更喜欢为更改设置动画):

-(void)keyboardWillShow:(NSNotification*)notification;
{
  NSDictionary *userInfo = [notification userInfo];
  NSValue *keyboardBoundsValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
  CGFloat keyboardHeight = [keyboardBoundsValue CGRectValue].size.width;

  CGFloat duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
  NSInteger animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];

  [UIView animateWithDuration:duration delay:0. options:animationCurve animations:^{
    [[self textView] setContentInset:UIEdgeInsetsMake(0., 0., keyboardHeight, 0.)];
    [[self view] layoutIfNeeded];
  } completion:nil];
}

答案 4 :(得分:0)

键盘出现时需要调整UITextView的大小。 因此,请查看我之前的回答here。 您需要调用以下方法来调整UITextView的大小,具体取决于键盘的宽度和文本:

- (CGFloat)textViewHeightForAttributedText:(NSAttributedString*)text andWidth:(CGFloat)width
{
    UITextView *calculationView = [[UITextView alloc] init];
    [calculationView setAttributedText:text];
    CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

您的代码使用我的方法:

- (void)keyboardWasShown:(NSNotification*)aNotification 
{ 
    NSDictionary* info = [aNotification userInfo]; 
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    // Get your text to NSAttributedString 
    NSAttributedString *as = [[NSAttributedString alloc] initWithString:self.notePad.text];

    // Resize UITextView
    self.notePad.frame = CGRectMake(0, 0, CGRectGetWidth(self.notePad.frame), [self textViewHeightForAttributedText:as andWidth:kbSize.width)]);
}

答案 5 :(得分:0)

我一直在与这个争斗一个星期,我发现将键盘大小的高度添加到底部contentInset不起作用。

有效的方法是从顶部减去它,如下:

UIEdgeInsets insets = UIEdgeInsetsMake(-(kbSize.height), 0.0, 0.0, 0.0);
[self.textView setContentInset:insets];