5

This question has been asked a couple of times, but I wasn't really able to find an answer...

In iOS6 I used the following to resize an UITextView whenever the keyboard appeared. Under iOS7 behavior is not as it should be (in my case, it seems like nothing is resizing at all). I suspect the cause to be the auto-layout / constraint behavior of iOS7. Any suggestions? ("notePad" is my 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;
}
4

6 回答 6

15

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

首先为您的底部布局指南约束定义一个 IBOutlet 并与故事板元素链接。

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

此方法支持方向更改和不同的键盘尺寸。希望能帮助到你。

于 2013-11-12T07:26:54.043 回答
4

您的代码在逻辑上是正确的。当键盘出现时,您几乎不应该使用滚动视图行为更改对象的框架,而应该只更改插图。插图应该相对于当前版本发生变化,因为 iOS7 负责调整导航栏。如果您提供新的插图,您可能会破坏 UI 中的某些内容。您的代码在 iOS7 上被破坏主要有两个原因:

  1. 您必须将自动布局约束添加到 textview 容器。(可能您的文本视图比您预期的要大)
  2. 你不应该以绝对的方式改变插图。

以下是正确配置 textview 的步骤

  • 在 xib(或情节提要)中,将约束添加到容器的顶部、左侧、右侧、底部(在我的情况下为 {0, 0, 0, 0},如下所示

自动布局约束

  • 注册键盘通知

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    
  • keyboardWillShow并且keyboardWillHide不改变框架,但相对于现有的改变插图。

    - (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;
    }
    
    • 然后记得移除观察者
于 2014-02-15T08:02:17.513 回答
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];
    }];
}
于 2015-02-26T14:29:17.430 回答
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];
}
于 2013-10-08T08:30:20.657 回答
0

当您的键盘出现时,您需要调整 UITextView 的大小。因此,请查看我在此处所做的先前答案。您需要根据键盘的宽度和文本调用以下方法来调整 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)]);
}
于 2013-10-07T16:07:07.797 回答
0

我已经为此奋斗了一个星期,我发现将键盘尺寸的高度添加到底部contentInset不起作用。

有效的是从顶部减去它,如下所示:

UIEdgeInsets insets = UIEdgeInsetsMake(-(kbSize.height), 0.0, 0.0, 0.0);
[self.textView setContentInset:insets];
于 2013-12-29T17:35:06.173 回答