简体   繁体   English

具有自动布局的程序化 UIScrollview

[英]Programmatic UIScrollview with Autolayout

After reading the technical notes on apple's website and reading matt neuburg's book on programming iOS 11 with a UIScrollview held in place with Autolayout, I have not been able to fully understand the concept of how it all works.在阅读了苹果网站上的技术说明并阅读了 matt neuburg 关于使用 Autolayout 固定的 UIScrollview 对 iOS 11 进行编程的书后,我一直无法完全理解它是如何工作的概念。

Basically what I want to have is a Scrollview that would have a child view ChildView where this child view then has a Textview .基本上我想要的是一个Scrollview ,它会有一个子视图ChildView ,然后这个子视图有一个Textview

Below I have attached the mockup of what I am trying to achieve Programmatically no-nibs, no storyboards.下面我附上了我试图以编程方式实现的模型,没有笔尖,没有故事板。

在此处输入图片说明

and as for the code, This is what I usually come up with:至于代码,这就是我通常想出的:

Code代码

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 
}

Please Note: for the ContentView , I normally define constraints to anchor the edges inside the scrollview but not in this case with Autolayout and the fact that I want it to scroll vertically upwards when the keyboard becomesFirstResponder .请注意:对于ContentView ,我通常定义约束来锚定滚动视图内的边缘,但在这种情况下没有使用 Autolayout 以及我希望它在键盘becomesFirstResponder时垂直向上滚动的becomesFirstResponder Another way I came up with this to try to work is to create a UIView that spans larger than the Scrollview to allow the child view to be a subview of this larger view that has the scroll view as its parent.我想出的另一种尝试工作的方法是创建一个跨度大于 Scrollview 的UIView ,以允许子视图成为这个更大视图的子视图,该视图将滚动视图作为其父视图。

My Problem: How can I achieve this from here onwards?我的问题:从这里开始我怎样才能做到这一点? Any suggestions?有什么建议吗? I have been giving it a thought to something like this: (ContentView would be the larger view that will allow this to be scrollable, and the child view would be the 3rd child view in the hierarchy)我一直在考虑这样的事情:(ContentView 将是允许它滚动的更大的视图,子视图将是层次结构中的第三个子视图)

在此处输入图片说明

  1. You don't need to create a faux content view, you can add subviews directly to the scroll view (and I prefer).你不需要创建一个虚假的内容视图,你可以直接向滚动视图添加子视图(我更喜欢)。 Apple does not recommend creating one, they only suggest that you can. Apple 不建议创建一个,他们只建议您可以。

  2. Subviews of the scroll view shall not rely on the scroll view to determine their sizes, only their positions.滚动视图的子视图不应依赖滚动视图来确定它们的大小,而只依赖于它们的位置。

  3. Your constraints must define the left-most, right-most, top-most, and bottom-most edges in order for auto layout to create the content view for you.您的约束必须定义最左侧、最右侧、最顶部和最底部的边缘,以便自动布局为您创建内容视图。

When you create a scroll view, you may give its frame the bounds of the controller's view:创建滚动视图时,您可以为其框架指定控制器视图的边界:

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

You must then set the boundaries of the content view by anchoring its subviews to the edges of the scroll view.然后,您必须通过将其子视图锚定到滚动视图的边缘来设置内容视图的边界。 To achieve vertical-only scrolling, your top-most view must be anchored to the top of the scroll view and none of the subviews anchored to the leading and trailing edges must exceed the width of the scroll view.要实现仅垂直滚动,您的最顶部视图必须锚定到滚动视图的顶部,并且锚定到前缘和后缘的子视图都不能超过滚动视图的宽度。

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

Notice the topMostView does not rely on the scroll view to determine its size, only its position.注意topMostView不依赖滚动视图来确定它的大小,只依赖于它的位置。 The content in your scroll view now has a height of 1000 but it won't scroll because nothing is anchored to the bottom of the scroll view.滚动视图中的内容现在具有1000的高度,但它不会滚动,因为没有任何内容锚定到滚动视图的底部。 Therefore, do that in your bottom-most view.因此,请在最底部的视图中执行此操作。

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

The last anchor may seem odd because you're anchoring a view that is 1000 points tall to an anchor that you just anchored to the bottom of the view which is definitely less than 1000 points tall.最后一个锚点可能看起来很奇怪,因为您将一个1000点高的视图锚定到您刚刚锚定到视图底部的锚点上,该锚点高度绝对小于1000点。 But this is how Apple wants you to do it.但这就是Apple希望您这样做的方式。 This way, you do not need to create a content view, auto layout does it for you.这样,您不需要创建内容视图,自动布局会为您完成。

This principle of defining the "edge constraints" (left-most, right-most, top-most, bottom-most) goes beyond scroll views.这种定义“边缘约束”(最左边、最右边、最顶部、最底部)的原则超越了滚动视图。 When you create a custom UITableViewCell using auto layout, defining the four edge constraints (ie where the top-most subview is anchored to the top of the cell topMostView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true , the bottom-most subview to the bottom of the cell bottomMostView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true , etc.) is how you create self-sizing cells.当您使用自动布局创建自定义UITableViewCell ,定义四个边缘约束(即最顶部的子视图锚定到单元格的顶部topMostView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true ,底部- 单元格底部的 -most 子视图bottomMostView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true等) 是您创建自行调整大小的单元格的方式。 It's how you create any self-sizing view, really.真的,这就是您创建任何自我调整大小视图的方式。

当您创建 scrollView 时,apple 建议在其中放置一个 contentView 并为该 contentView 指定 viewController 视图的宽度并将其顶部、底部、前导、尾随约束固定到滚动视图,然后开始从上到下放置项目想要并将最底部的项目固定到 scollview 的 contentView 的底部,这样滚动视图可以呈现它的高度,这个底部约束可以随你喜欢,并且根据它滚动视图将继续滚动直到完成它

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM