Autolayout的程序化UIScrollview [英] Programmatic UIScrollview with Autolayout

查看:133
本文介绍了Autolayout的程序化UIScrollview的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,在阅读了Apple网站上的技术说明并阅读了有关使用Autolayout的UIScrollview的iOS 11编程的matt neuburg的书之后,我无法完全理解这一切的概念。

So 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.

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

Basically what I want to have is a Scrollview that would have a child view ChildView where this child view then has a Textview.

下面我附上了我想要实现的模型编程 no-nibs ,没有故事板。

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:

代码

 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以及我希望它在键盘 becomeFirstResponder 时垂直向上滚动的事实。我想出办法尝试工作的另一种方法是创建一个大于Scrollview的 UIView ,以允许子视图成为这个更大视图的子视图滚动视图作为其父级。

Pleae 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. 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.

我的问题:如何从此开始实现此目的?有什么建议么?
我一直在考虑这样的事情:( ContentView将是允许这个可滚动的更大视图,子视图将是hiarchy中的第3个子视图)

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 hiarchy)

推荐答案

我是仔细阅读关于 UIScrollView 的Apple文档,特别是如何使用自动布局,我也喜欢编程路径。首先,您不需要创建一个虚假的内容视图,您可以直接将子视图添加到滚动视图(我更喜欢这个,因为我认为一个虚假的视图是一个无关的对象)。 Apple,AFAIK,不建议创建一个,但仅建议您可以。而且,据我记忆,他们已经制作了他们没有的例子。其次,滚动视图中的子视图不应该(可能不能)依赖滚动视图来确定它们的宽度或高度。第三,您的约束必须从左到右和从上到下链接到自动布局,以便为您创建内容视图。第三条规则可能有点令人困惑甚至看起来违反直觉,但这正是Apple希望你构建滚动视图的方式。

I've carefully read Apple's documentation on UIScrollView and specifically how it works with auto layout and I, too, prefer the programmatic path. First, you don't need to create a faux content view, you can add subviews directly to the scroll view (and I prefer this as I consider a faux view an extraneous object). Apple, AFAIK, does not recommend creating one but merely suggests that you can. And, as far as I remember, they have produced examples where they don't. Second, subviews within the scroll view should not (possibly must not) rely on the scroll view to determine their widths or heights. And third, your constraints must be chained from left-to-right and top-to-bottom for auto layout to create the content view for you. The third "rule" can be a bit confusing or even seem counterintuitive but it is exactly how Apple wants you to construct your scroll view.

具体来说,当你创建时滚动视图您可以为其框架提供控制器视图的边界:

To be specific, 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. Therefore, your top-most view must be anchored to the top of the scroll view and its width cannot exceed the width of the scroll view (which is the width of the view) (if your goal is vertical-only scrolling).

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 不依赖于滚动视图来确定其大小(仅限其位置)。

Notice the topMostView does not rely on the scroll view to determine its size (only its position).

滚动视图中的内容现在具有高度 1000 但它不会滚动,因为没有任何东西锚定在滚动视图的底部。因此,请在最底层的视图中执行此操作。

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. 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

最后一个锚似乎违反直觉,因为你正在锚定一个<$ c $的视图c> 1000 指向您刚刚锚定到视图底部的锚点,该锚点肯定小于 1000 点高。但这就是Apple希望你这样做的方式。使用这种方法,您不仅不需要创建内容视图,实际上您可以假装它不存在 - 当然,除非您需要其仍然可以从滚动视图的属性中读取的边界。

The last anchor can seem counterintuitive 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. But this is how Apple wants you to do it. With this approach, not only do you not need to create a content view, you can in effect pretend it doesn't exist–unless, of course, if you need its bounds which can still be read from the scroll view's properties.

事实上,这个原则超越了滚动视图。当您使用自动布局创建自定义 UITableViewCell 时,从左到右和从上到下链接您的约束,其中最顶部的子视图锚定到顶部单元格( topMostView.topAnchor.constraint(equalTo:self.topAnchor).isActive = true )和单元格底部的最底部子视图( bottomMostView.topAnchor.constraint(equalTo:self.bottomAnchor).isActive = true )并且您有自定义单元格。

In fact, this principle goes beyond scroll views. When you create a custom UITableViewCell using auto layout, chain your constraints left-to-right and top-to-bottom where the top-most subview is anchored to the top of the cell (topMostView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true) and the bottom-most subview to the bottom of the cell (bottomMostView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true) and you have self-sizing cells.

这篇关于Autolayout的程序化UIScrollview的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆