【问题标题】:Autolayout Constraint - Keyboard自动布局约束 - 键盘
【发布时间】:2012-10-07 03:21:58
【问题描述】:

我一直在尝试平滑地为具有自动布局约束的表格视图设置动画。我在我的 .h 中引用了约束“keyboardHeight”,并在 IB 中将其链接起来。我要做的就是在弹出时使用键盘为表格视图设置动画。这是我的代码:

- (void)keyboardWillShow:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [kbFrame CGRectValue];
    CGFloat height = keyboardFrame.size.height;

    [UIView animateWithDuration:animationDuration animations:^{
        self.keyboardHeight.constant = -height;
        [self.view setNeedsLayout];
    }];
}

问题是动画块是瞬时的,我看到在键盘完成动画之前出现空白。所以基本上我在键盘动画时看到视图的白色背景。只要键盘在动画,我就无法让动画持续。

我是不是以错误的方式处理这个问题?提前致谢!

【问题讨论】:

  • 嘿,已经有一段时间了,但你忘记了动画类型: UIViewAnimationOptions animationOptions = [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];

标签: objective-c ios uikeyboard autolayout


【解决方案1】:

试试这个方法:

self.keyboardHeight.constant = -height;
[self.view setNeedsUpdateConstraints];

[UIView animateWithDuration:animationDuration animations:^{
   [self.view layoutIfNeeded];
}];

记住这个模式,因为这应该是更新基于约束的布局的正确方法(根据 WWDC)。也可以添加或删除NSLayoutConstraints,只要之后调用setNeedsUpdateConstraints即可。

【讨论】:

  • 太好了,谢谢。所以我想弄清楚这里的工作流程。我先设置约束,告诉视图约束已经改变,需要更新。然后在动画块中我更新视图。为什么我不能将键盘高度命令内联放置在块中,这对我来说很奇怪。这是因为视图层次结构吗?非常感谢您的帮助,我将尝试找到更多关于此主题的 WWDC 视频!
  • 从技术上讲,您可以在动画块内设置键盘高度。重要的是在layoutIfNeeded之前致电setNeedsUpdateConstraints。我个人的习惯是尽可能只在块内包含相关方法(在这种情况下,只在动画块内调用你想要动画的东西)。
  • 非常感谢您的帮助!
  • 其实用这个方法视图还是会跳给我的……布局引擎会马上用新的高度来布局,那它什么时候有机会做动画呢?
  • setNeedsUpdateConstraints 不会立即触发布局。在这个 sn-p 中,布局发生在动画块内,这正是我们想要的。现在,如果您正在跳跃,那么可能是其他地方触发了布局(动画仅在属性上发生两个动画时“跳跃”;第二个动画取消第一个动画)
【解决方案2】:

如果您使用的是 UITableViewController,则 iOS 应自动适应键盘大小以调整 contentInsets。但是如果你的 tableView 在 UIViewController 中,你可能想使用这个:

KeyboardLayoutConstraintSpring 框架中。到目前为止我找到的最简单的解决方案。

【讨论】:

    【解决方案3】:

    尝试下一个代码。在这种情况下,表格视图布局在屏幕的底部边缘。

    - (void)keyboardWillShow:(NSNotification *)notification { // UIKeyboardWillShowNotification
    
        NSDictionary *info = [notification userInfo];
        NSValue *keyboardFrameValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
        NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
    
        BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation);
        CGFloat keyboardHeight = isPortrait ? keyboardFrame.size.height : keyboardFrame.size.width;
    
        // constrBottom is a constraint defining distance between bottom edge of tableView and bottom edge of its superview
        constrBottom.constant = keyboardHeight; 
        // or constrBottom.constant = -keyboardHeight - in case if you create constrBottom in code (NSLayoutConstraint constraintWithItem:...:toItem:...) and set views in inverted order
    
        [UIView animateWithDuration:animationDuration animations:^{
            [tableView layoutIfNeeded];
        }];
    }
    
    
    - (void)keyboardWillHide:(NSNotification *)notification { // UIKeyboardWillHideNotification
    
        NSDictionary *info = [notification userInfo];
        NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    
        constrBottom.constant = 0;
        [UIView animateWithDuration:animationDuration animations:^{
            [tableView layoutIfNeeded];
        }];
    }
    

    【讨论】:

    • 动画并不完美。视图不随键盘移动。键盘显示有延迟,大约一秒钟后出现。
    • @GabrielDiaconescu 我没有遇到任何延迟
    • 这对我来说在 iOS7 上运行良好。然而,在 iPad 上的 iOS8 在横向模式下,keyboardFrame 宽度与 keyboardFrame 高度交换。我正在尝试为 iOS8 找到一个漂亮的修复程序。
    • iOS8上iPhone+iPad的解决方案:CGRect keyboardFrame = [keyboardFrameValue CGRectValue]; CGFloat keyboardHeight = keyboardFrame.size.height;
    【解决方案4】:

    我采用的方法是添加一个遵循键盘大小的视图。将其添加到您的表格视图或文本输入或其他任何内容下方,当键盘出现时它会向上推。

    这就是我设置视图层次结构的方式:

    NSDictionary *views = @{@"chats": self.chatsListView, @"reply": self.replyBarView, @"fakeKeyboard":self.fakeKeyboardView};
    [self.view addVisualConstraints:@"V:|-30-[chats][reply][fakeKeyboard]|" views:views];
    

    然后键盘尺寸跟随视图的关键位如下所示:

    - (void)keyboardWillShow:(NSNotification *)notification
    {
        // Save the height of keyboard and animation duration
        NSDictionary *userInfo = [notification userInfo];
        CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
        self.desiredHeight = CGRectGetHeight(keyboardRect);
        self.duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
    
        [self animateSizeChange];
    }
    
    - (void)keyboardWillHide:(NSNotification *)notification
    {
        self.desiredHeight = 0.0f;
    
        [self animateSizeChange];
    }
    
    - (CGSize)intrinsicContentSize
    {
        return CGSizeMake(UIViewNoIntrinsicMetric, self.desiredHeight);
    }
    
    - (void)animateSizeChange
    {
        [self invalidateIntrinsicContentSize];
    
        // Animate transition
        [UIView animateWithDuration:self.duration animations:^{
            [self.superview layoutIfNeeded];
        }];
    }
    

    让这个特定视图处理其大小调整的好处是,您可以让视图控制器忽略它,并且您还可以在您的应用程序中任何您想要向上移动所有内容的地方重新使用此视图。

    完整文件在这里: https://gist.github.com/shepting/6025439

    【讨论】:

      猜你喜欢
      • 2016-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-17
      • 1970-01-01
      相关资源
      最近更新 更多