【问题标题】:Programmatic UIScrollview with Autolayout带有自动布局的程序化 UIScrollview
【发布时间】:2018-06-21 08:35:29
【问题描述】:

在阅读了苹果网站上的技术说明并阅读了 matt neuburg 关于使用 Autolayout 保持 UIScrollview 进行 iOS 11 编程的书后,我无法完全理解它是如何工作的概念。

基本上我想要的是一个 Scrollview,它会有一个子视图 ChildView,而这个子视图然后有一个 Textview

下面我附上了我试图以程序化无笔尖,无情节提要实现的目标的模型。

至于代码,这是我通常想出的:

代码

let Scroller: UIScrollView = {
    let scroll = UIScrollView()
    scroll.translatesAutoresizingMaskIntoConstraints = false
    scroll.backgroundColor = UIColor.alizarinColor()
    return scroll
}()

// Content view

let ContentView : UIView = {

    let content = UIView()
    content.translatesAutoresizingMaskIntoConstraints = false
    content.backgroundColor = UIColor.blue
    return content
}()

override func viewDidLoad() {

    super.viewDidLoad()

    self.view.addSubview(Scroller)

    // Auto layout
    Scroller.leftAnchor.constraint(equalTo: view.leftAnchor, constant:0).isActive = true
    Scroller.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
    Scroller.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
    Scroller.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true

    Scroller.addSubview(ContentView)
    // Undefined Content view 
}

请注意: 对于 ContentView,我通常会定义约束来锚定滚动视图内的边缘,但在这种情况下不会使用 Autolayout 以及我想要它的事实当键盘becomesFirstResponder 时垂直向上滚动。我想出的另一种尝试工作的方法是创建一个跨越比滚动视图更大的UIView,以允许子视图成为这个以滚动视图作为其父视图的更大视图的子视图。

我的问题:从这里开始我该如何实现呢?有什么建议? 我一直在考虑这样的事情:(ContentView 将是允许滚动的较大视图,子视图将是层次结构中的第三个子视图)

【问题讨论】:

  • 您的滚动视图的子视图永远不会大于滚动视图。 (更像是小于或等于)。比如说你有这个UIView (height = 500),这个高度非常适合 (iphone 6 ,但不适用于 (iphone 5 >=) .与其单独使用视图,不如添加一个scrollview(如果需要,高度 = 500 或屏幕大小+额外填充到其内容高度)并将所需视图包装为其子视图,那么您的问题是固定。

标签: ios swift uiscrollview autolayout


【解决方案1】:
  1. 您不需要创建虚假内容视图,您可以将子视图直接添加到滚动视图(我更喜欢)。 Apple 不建议创建一个,他们只建议您可以。

  2. 滚动视图的子视图不应依赖滚动视图来确定它们的大小,只依赖它们的位置。

  3. 您的约束必须定义最左侧、最右侧、最顶部和最底部边缘,以便自动布局为您创建内容视图。

当你创建一个滚动视图时,你可以给它的框架赋予控制器视图的边界:

scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true

然后,您必须通过将其子视图锚定到滚动视图的边缘来设置内容视图的边界。要实现仅垂直滚动,您的最顶层视图必须锚定到滚动视图的顶部,并且锚定到前缘和后缘的任何子视图都不得超过滚动视图的宽度。

topMostView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(topMostView)
topMostView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
topMostView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
topMostView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
topMostView.heightAnchor.constraint(equalToConstant: 1000).isActive = true

注意topMostView 不依赖滚动视图来确定它的大小,只依赖它的位置。滚动视图中的内容现在具有1000 的高度,但它不会滚动,因为没有任何东西被锚定到滚动视图的底部。因此,请在最底部的视图中执行此操作。

bottomMostView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(bottomMostView)
bottomMostView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
bottomMostView.topAnchor.constraint(equalTo: topMostView.bottomAnchor).isActive = true
bottomMostView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
bottomMostView.heightAnchor.constraint(equalToConstant: 1000).isActive = true

bottomMostView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

最后一个锚点可能看起来很奇怪,因为您将一个 1,000 点高的视图锚定到一个您刚刚锚定到视图底部的锚点,该底部肯定小于 1,000 点高。但这就是苹果希望你这样做的方式。通过这样做,您不需要创建内容视图,自动布局会为您完成。

定义“边缘约束”(最左侧、最右侧、最顶部、最底部)超出了滚动视图的范围。当您创建自定义UITableViewCell 时,例如,使用自动布局,定义四个边缘约束(即最顶部的子视图锚定到单元格的顶部topMostView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true,最底部的子视图到底部单元格bottomMostView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true 等)是您创建自定大小单元格的方式。实际上,定义边缘约束是您创建任何自定尺寸视图的方式。

【讨论】:

  • 非常感谢@iabuseservers。这真太了不起了。解释效果很好,我确实测试了将子视图放置到这两个视图中。那么在这些视图中约束对象是否安全?我将约束它们的方式是使用堆栈视图。让我知道这样做是否安全
  • 你一定要给滚动视图约束的子视图。你绝对可以在滚动视图中放置一个堆栈视图;只需确保将堆栈视图正确锚定到滚动视图以拉伸其内容区域。
  • 很好的答案,感谢您的帮助。 FWIW,我不肯定你绝对必须从 L->R 和 T->B 进行限制。
  • 如果您正在寻找此答案的不同措辞。那你可以看看这个other answer
  • 惊人的解释!但是,如果我想将视图锚定到滚动视图的右侧怎么办?有没有办法做到这一点?
【解决方案2】:

当你创建一个 scrollView 时,Apple 建议在其中放置一个 contentView 并为该 contentView 赋予 viewController 视图的宽度,并将它的顶部、底部、前导、尾随约束固定到滚动视图,然后首先将项目从顶部放置到底部,并将最底部的项目固定到 scollview 的 contentView 的底部,所以滚动视图可以呈现它的高度,这个底部约束可以是你喜欢的,并且根据它滚动视图将继续滚动直到完成它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    • 2015-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多