How can I use Autolayout to set constraints on my UIScrollview?

后端 未结 18 1596
别那么骄傲
别那么骄傲 2020-11-28 00:43

I have spent two days trying out the various solutions for Mixed and Pure Autolayout approaches to achieve what was a trivial scrollview setup prior to autolayout, and it\'s

相关标签:
18条回答
  • 2020-11-28 01:22

    Similar problem I'm having today with iOS 8.4, Xcode 6.4

    There a view containing a scroll view, containing a contentView (UIView) containing subviews.

    Everything is auto layout everywhere. The scrollview edges are pinned to the parent views edges with constraints. The content view edges are pinned to the scroll view edges with constraints.

    Originally the content view would refuse to size as the full width of the scroll view. I had to add an additional constraint on the content view to have its width match the parent scroll view. Or I could set a contentView.centerX == scrollView.centerX constraint. Either one of those in addition to pinning the edges suddenly made the content view properly size.

    // Either one of these additional constraints are required to get autolayout to correctly layout the contentView. Otherwise contentView size is its minimum required size
    scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1.0, constant: 0))
    scrollView.addConstraint(NSLayoutConstraint(item: contentView, attribute: NSLayoutAttribute.Width, relatedBy: .Equal, toItem: scrollView, attribute: .Width, multiplier: 1.0, constant: 0.0))
    

    Pinning the edges of the content view to the scroll view using visual constraints of the form,

    let cvConstraints = ["H:|[contentView]|", "V:|[contentView]|"]
    

    I use a routine to iterate through the array and add them to the scrollView.

    0 讨论(0)
  • 2020-11-28 01:22

    I faced a similar problem. I set every constrained and was always wondering why it still resizes some subviews. My solution was to set clipsToBounds to YES.

    0 讨论(0)
  • 2020-11-28 01:24

    If like me you just use static content without counstraints inside the subview, like you can do like this:

    override func viewDidLayoutSubviews() {
        scrollView.contentSize = CGSizeMake(320, 800)
    }
    
    0 讨论(0)
  • 2020-11-28 01:25

    The pure autolayout approach works beautifully but it is quite a pain to get set up if you're migrating from non-autolayout. I've done it a few times now and I have a few general tips:

    • Start small: even if it means recreating your storyboard views, start with just a few elements and build your views slowly, making sure to test that scrolling works after adding a few elements.
    • Turn off translatesAutoresizingMaskIntoConstraints on everything: this was always the the cause of constraint conflicts for me.
    • Set your UIScrollView constraints properly: make sure the scroll view is connected on all sides to the parent view, otherwise it just won't expand at all.
    0 讨论(0)
  • 2020-11-28 01:27

    I assume you are running into issues with thecontentSize. Check out this blog post on how to handle the contentSize when using a "pure" AutoLayout approach. The gist of it is that your constraints implicitly define the content size. You NEVER set it explicitly when using AutoLayout. I've attached example project at the end of the blog post to demonstrate how it works

    0 讨论(0)
  • 2020-11-28 01:30

    The following solution worked for me for scrollView with autolayout and without contentSize:

    1. Drag n drop a scrollView to viewController and apply whatever constraints to cover the space you want.
    2. Drag n drop a UIView inside the scrollView and make it cover the whole space of scrollView and apply constraints to be top, left, right, bottom space from scrollView.
    3. Set the height (and width if horizontal scrolling is required) of the inner view as per the need of scrolling. This part can also be done from code if required.
    4. Critical. After you set the height to some large value in point (3), go back to point (2) and be certain to set the top, left, right, bottom values back to zero as Xcode may have changed them for you when you force changed the height in (3).

    And you're done. Now, you can add any number of controls on this view and apply the constraints relevant to each other (which don't seem working without this view). If you don't want to use this view then you'll have to apply constraints for each control related to scrollView (not related to each other).


    The overwhelming tip..............

    Critical. Let's say for clarity the UIScrollView is 1000 wide and 100 high. (In fact normally these values would be dynamic, of course, depending on the width of the device etc. But for now just say 1000 wide and 100 high.) Let's say you are doing a horizontal scroll. So put a UIView inside the UIScrollView. (That is the "content view".) Set all four constraints of the content view top, bottom, leading, trailing, to the scroll view. Make them all zero even if that seems wrong. Set the height of the content UIView to 100 and forget about that. Now: you want to scroll horizontally, so set the width of the content view to be let's say 1225.

    Note that the width of the content view is now 225 bigger than the width of the parent scroll view. That's OK: in fact, you MUST do that. Note that

    ...you do NOT set the trailing width to negative 225...

    you would think you have to "match" the widths as you normally would. But if you do that, it will not work at all.

    You must set the leading and trailing numbers to ZERO, never negative (even though the width is "bigger")

    Interestingly, you can actually set the leading/trailing numbers to any positive value (try say "50") and it gives you kind of a margin of the bounce. (It often looks great: try it.) Any negative value on either end will "silently break".

    Note that, infuriatingly, often Xcode (as of 7.3.1 anyway),

    will 'helpfully' set those values for you to negative numbers!

    because it tries to automatically tally them for you. If so it will silently break. Set all four values to zero in the first instance. And set the width of the content view much wider than the "1000" in the example.


    Edited: I've ended up with using UITableView instead of UIScrollView for most of my requirement. As tableView seems to me much more flexible and dynamic.

    0 讨论(0)
提交回复
热议问题