ios - scrollView 的 ContentInset

标签 ios swift user-interface uiscrollview keyboard-events

这是我的 View ,左边是键盘不显示时的 View ,右边是键盘显示时我想要实现的 View 。

enter image description here

我所有的字段都被添加到一个 ScrollView ,然后我像这样设置约束,field1 topConstraint 设置为 scrollView top,field4 bottomConstraint 设置为 scrollView bottom。所有其他字段都附加到下面的字段。

正如您从最右边的模型中看到的那样,当显示键盘时,我想像那样重新调整 View 。所以我现在正在做的是:

func keyboardWillShow(notification: NSNotification) {
       self.field2.snp_updateConstraints { make -> Void in
          make.bottom.equalTo(self.field3.snp_top).offset(8)
       }

用这个我调整了 field2 和 field3 之间的大空间,到目前为止一切顺利。然后我继续设置 contentInset:

    let contentInset = UIEdgeInsetsMake(0, 0,getKeyboardSize(notification).height, 0)

    self.scrollView.contentInset = contentInset
    self.scrollView.scrollIndicatorInsets = contentInset

但是 scrollView 没有按照我想要的方式调整,因为 field3 仍然隐藏在键盘后面的一半。

写这篇文章的原因是我显然不明白 contentInsets 如何与 scrollView 一起工作,我想避免手动设置 contentOffset,如果可能的话。

我设置的约束似乎有问题。 field4 的当前约束是我将它设置为绑定(bind)到 View 而不是 scrollView 底部,并且我将 scrollView 的每个边缘设置为绑定(bind)到 View 。

更新: 如果我将 field4 底部约束设置为绑定(bind)到 scrollView,则 scrollViews 高度为 0,如果我之前将 scrollView 设置为与 View 本身一样大,它怎么会不知道它应该是什么大小?这让我很困惑..

更新 2 我正在像这样设置 scrollView 约束:

    self.scrollView.snp_makeConstraints { make -> Void in
        make.top.equalTo(self.snp_topLayoutGuideBottom)
        make.left.right.equalTo(self.view)
        make.bottom.equalTo(self.snp_bottomLayoutGuideBottom)
    }

从 UIDebugger 我可以看到 scrollView 的高度是一样的,但是 Y 坐标已经变成了 20,但是我仍然不能在其中滚动??此外,在调试时,我可以将 scrollViews contentSize 设置为大于框架,这意味着它应该是可滚动的,但事实并非如此。

更新 3 我现在明白 Field1 和 Field4 都需要附加到 scrollViews 的顶部和底部。因此,scrollViews frame 和 scrollViews contentSize 之间存在差异,因为当 contentSize > frame scrollView 可滚动时,它按预期工作。 所以这对我来说是向前迈出的一大步,现在唯一奇怪的是 contentInset。

我对 contentInset 的理解是,您可以指定 View 在任一方向上应该缩小多少。所以就像现在一样,我正在使用 scrollView 底部的键盘高度进行插入,但它没有滚动,但是当我将顶部 contentInset 设置为某个随机负数(如 -100)时,它会滚动,为什么调整底部插图时未实现此行为?

最佳答案

所以我用下面的方法解决了这个问题:

我确保为 ScrollView 设置了 Field1 和 Field4 约束,这样 ScrollView 就可以自动计算高度,并且如果某些内容在 View 之外也可以滚动。然后我从键盘顶部和框架计算出可见框架。

   func keyboardWillShow(notification: NSNotification) {

    self.Field2.snp_updateConstraints { make -> Void in
         make.bottom.equalTo(self.Field3.snp_top)
    }

    self.Field3.snp_updateConstraints { make -> Void in
         make.bottom.equalTo(self.Field4.snp_top)
    }

    self.view.layoutIfNeeded()

    let contentInset = UIEdgeInsetsMake(0, 0,getKeyboardSize(notification).height + 4, 0)
    let visibleRect = UIEdgeInsetsInsetRect(self.scrollView.frame, contentInset)
    let scrollToOffset = max(0,self.Field4.frame.maxY - visibleRect.height)
    self.scrollView.setContentOffset(CGPoint(x: 0, y: scrollToOffset), animated: true)
 }

关键是在更改约束后,我需要使当前布局无效并重新布局 View ,这样我们就可以计算更新的约束在哪里可以正确完成。

关于ios - scrollView 的 ContentInset,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38832770/

相关文章:

Swift - 如何在自定义类中设置 UIBarButtonItem 的图像

java - 如何在 JPanel 类中创建 JList "refresh"方法

ios - 不同类型的 Json 属性

ios - 将 UIWindow rootViewController 从 UIViewController 重新分配给包含 UINavigationControllers 的 UITabBarController

iphone - SDWebImage 操作未被取消

html - <button> 有什么好的做法?它可以替代 <a> 还是仅用于表单?

Android - 卡片 UI 框架

iphone - Objective-C:为什么@synthesize 预见到一个赋值?

ios - 快速在 TableView 内的 Collection View 中显示内容时出现问题

ios - 我希望打印的值太长,无法打印 firebase 中的所有值