【问题标题】:Resize a view when a keyboard appears (iOS)出现键盘时调整视图大小 (iOS)
【发布时间】:2013-04-09 05:33:20
【问题描述】:

我意识到有很多类似的解决方案,例如TPKeyboardAvoidingApple's famous solution,以及涉及使用 UIScrollView 的各种建议。就我而言,我需要调整视图的大小以适应键盘,而不是滚动或移动它。 This solution 最接近我想要实现的目标,所以这是我的基础。但是,我在使事情在横向模式下工作时遇到问题。我在键盘出现时调整视图大小的方法是这样的:

- (void)keyboardWillShow:(NSNotification *)note {
    NSDictionary *userInfo = note.userInfo;
    NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];

    CGRect keyboardFrame = [[self textField].superview convertRect:[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] fromView:nil];
    CGRect statusBarFrame = [[self textField].superview convertRect:[UIApplication sharedApplication].statusBarFrame fromView:nil];

    CGRect bounds = [self textField].superview.bounds;    
    CGRect newFrame = CGRectMake(0.0, 0.0, bounds.size.width, keyboardFrame.origin.y + statusBarFrame.size.height);
    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
        [self textField].superview.frame = newFrame;
    } completion:nil];
}

这在纵向模式下完美运行。

但是,在横向模式下,视图会根据设备旋转的方向从左到右或从右到左调整大小,而不是从下向上调整。

很明显,我使用坐标的方式有问题,并且在横向模式下某些参考框架不是我认为的那样,但我有一段时间整理一下如何解决它.我已经尝试使用 -convertRect: 转换各种东西:但我没有尝试任何东西。

我真的希望那些对所有这些矩形以及它们在方向变化时如何变化不那么困惑的人能够发现我做错了什么以及我需要做些什么才能做到这一点。作为参考,我 created a project 展示了重现我遇到的问题的最简单案例。

【问题讨论】:

  • 你想在键盘可见时转动iPan?
  • 理想情况下,是的,因为我确信有些用户会这样做。但我认为,如果我能让这个解决方案发挥作用(我正在添加一个方法,当键盘被隐藏以重新调整视图大小时)它会自动工作。我相信当设备旋转并显示键盘时,iOS会连续发送keyboardWillHide和keyboardWillShow通知。
  • 感谢动画代码,非常好用。
  • 这里curve的使用其实是不正确的。看到这个线程:stackoverflow.com/questions/18957476/ios-7-keyboard-animation/…

标签: iphone ios ipad keyboard landscape-portrait


【解决方案1】:

我不建议你为你的视图控制器调整根视图的大小,你可以创建 contentView 并添加到视图控制器的视图中。您可以按如下方式更改此 contentView 的大小(我不使用自动布局):

- (void)keyboardWillShow:(NSNotification *)note {
    NSDictionary *userInfo = note.userInfo;
    NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];

    CGRect keyboardFrameEnd = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardFrameEnd = [self.view convertRect:keyboardFrameEnd fromView:nil];

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
        self.contentView.frame = CGRectMake(0, 0, keyboardFrameEnd.size.width, keyboardFrameEnd.origin.y);
    } completion:nil];
}

- (void)keyboardWillHide:(NSNotification *)note {
    NSDictionary *userInfo = note.userInfo;
    NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];

    CGRect keyboardFrameEnd = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardFrameEnd = [self.view convertRect:keyboardFrameEnd fromView:nil];

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
        self.contentView.frame = CGRectMake(0, 0, keyboardFrameEnd.size.width, keyboardFrameEnd.origin.y);
    } completion:nil];
}

【讨论】:

  • 非常感谢!调整我的根视图的大小是我唯一的问题吗? (除了不删除自己作为 dealloc 上的观察者并且在隐藏键盘时没有运行代码;我在实际应用程序中有这些。)
  • 现在应用程序非常简单,因此很难谈论更多问题:)。未来可能出现的问题,您总能在这里解决。
  • 两个通知处理程序中的代码是相同的,因此可以使用一种方法而不是两种方法。
【解决方案2】:

试试这个方法。根据您的要求进行编辑。

#define kOFFSET_FOR_KEYBOARD 280.0

- (void)keyboardWillHide:(NSNotification *)notif {
    [self setViewMoveUp:NO];
}


- (void)keyboardWillShow:(NSNotification *)notif{
    [self setViewMoveUp:YES];
}


- (void)textFieldDidBeginEditing:(UITextField *)textField {
    stayup = YES;
    [self setViewMoveUp:YES];
}


- (void)textFieldDidEndEditing:(UITextField *)textField {
    stayup = NO;
    [self setViewMoveUp:NO];
}

//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMoveUp:(BOOL)moveUp
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3]; // if you want to slide up the view
    [UIView setAnimationBeginsFromCurrentState:YES];

    CGRect rect = self.view.frame;
    if (moveUp)
    {
        // 1. move the view's origin up so that the text field that will be hidden come above the keyboard 
        // 2. increase the size of the view so that the area behind the keyboard is covered up.

        if (rect.origin.y == 0 ) {
            rect.origin.y -= kOFFSET_FOR_KEYBOARD;
            //rect.size.height += kOFFSET_FOR_KEYBOARD;
        }

    }
    else
    {
        if (stayup == NO) {
            rect.origin.y += kOFFSET_FOR_KEYBOARD;
            //rect.size.height -= kOFFSET_FOR_KEYBOARD;
        }
    }
    self.view.frame = rect; 
    [UIView commitAnimations];
}

【讨论】:

  • 谢谢,但这会移动视图 - 我需要调整我的大小 - 并通过硬编码值;我更喜欢在运行时找到他们键盘的大小,以防未来。
【解决方案3】:

【讨论】:

  • 您是否尝试过该解决方案?它不起作用。我在最初的问题中提到了这一点。
【解决方案4】:

我已经完成了,希望这段代码对你有所帮助。

- (void)viewWillAppear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

- (void)keyboardWillShow:(NSNotification*)notification
{
    [self moveControls:notification up:YES];
}

- (void)keyboardWillBeHidden:(NSNotification*)notification
{
    [self moveControls:notification up:NO];
}

- (void)moveControls:(NSNotification*)notification up:(BOOL)up
{
    NSDictionary* userInfo = [notification userInfo];
    CGRect newFrame = [self getNewControlsFrame:userInfo up:up];

    [self animateControls:userInfo withFrame:newFrame];
}

- (CGRect)getNewControlsFrame:(NSDictionary*)userInfo up:(BOOL)up
{
    CGRect kbFrame = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    kbFrame = [self.view convertRect:kbFrame fromView:nil];

    CGRect newFrame = self.view.frame;
    newFrame.origin.y += kbFrame.size.height * (up ? -1 : 1);

    return newFrame;
}

- (void)animateControls:(NSDictionary*)userInfo withFrame:(CGRect)newFrame
{
    NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];

    [UIView animateWithDuration:duration
                          delay:0
                        options:animationOptionsWithCurve(animationCurve)
                     animations:^{
                         self.view.frame = newFrame;
                     }
                     completion:^(BOOL finished){}];
}

static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve curve)
{
    return (UIViewAnimationOptions)curve << 16;
}

【讨论】:

【解决方案5】:

Vitaliy B 的回答很快。我有一个名为 templateHeaderContentView 的视图,我创建了一个函数并在那里配置了视图高度。您可以使用自己的视图并在那里相应地更改高度。

func keyboardWillShow(notification: NSNotification) {
    keyboardShowOrHide(notification)
}

func keyboardWillHide(notification: NSNotification) {
    keyboardShowOrHide(notification)
}

private func keyboardShowOrHide(notification: NSNotification) {
    guard let userInfo = notification.userInfo else {return}
    guard let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey]else { return }
    guard let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] else { return }
    guard let keyboardFrameEnd = userInfo[UIKeyboardFrameEndUserInfoKey] else { return }

    let curveOption = UIViewAnimationOptions(rawValue: UInt(curve.integerValue << 16))
    let keyboardFrameEndRectFromView = view.convertRect(keyboardFrameEnd.CGRectValue, fromView: nil)
    UIView.animateWithDuration(duration.doubleValue ?? 1.0,
        delay: 0,
        options: [curveOption, .BeginFromCurrentState],
        animations: { () -> Void in
            self.templateHeaderContentView.configureView(keyboardFrameEndRectFromView.origin.y)
        }, completion: nil)
}

【讨论】:

  • 我使用了 Vitaily 的答案,但考虑为后代包括 configureView 功能;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
  • 2015-08-21
  • 1970-01-01
  • 2011-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多