0

So I wanna use a scrollview, while also fitting the width of it to the screen size of each device automatically.

So on iPhone 6+, and on iPhone 5 the inner UIView that is within the UIScrollView would fill the width of the UISCrollView. The constraints of the objects within the UIView and the UIView should reposition the inner content to fit the actual final width.

The problem I am having is that I know how to make the UIScrollView to fit the screen it is being hosted in, and I know how to create the constraints of the objects within the UIView to the UIView itself, and these all seem to work.
BUT - I couldn't find out how to make the UIView that contains the content to change its width to fit the UIScrollView.

Setting constraints do not help between the scrollView and the UIView which is the immediate kid. I think this because of the "content" vs. "frame" discussion they have on Apple web-site"
Changing the frame parameters in code is being ignored (probably because it is part of an AutoLayout storyboard):

var currSize = contentView.frame;
currSize.size.width = UIScreen.mainScreen().bounds.width;
contentView.frame = currSize;

I do want to have Autolayout within the inner UIView as described above,
I do want the UIScrollView to fit the whole screen.

What should I do??

-> I want to configure the "View" to fit the size of the "ScrollView" which it is in, but any AutoLayout constraint is being wrong to configure (since it does not apply on the content size) and code is being ignored because of auto layout.

These are the objects and constraints: enter image description here

evenro
  • 2,626
  • 20
  • 35

3 Answers3

2

The problem is that you have not given the content view any width/height constraints. Just provide them and all will be well.

What you're not understanding is that the constraints between the edges of the "content view" and its surrounding scroll view have a special meaning - they dictate the contentSize of the scroll view. They don't do what you want - they don't have any effect on the content view's size. The content view must get its size from the inside out, as it were. This can be due to its subviews' constraints (pushing outward, as it were) or to its own width and height constraints.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I can't give it, because I don't know it in advance.. it depends on the screen size.. and changes... – evenro Sep 28 '14 at 22:23
  • @evenro: The screen width / height constraint works out of the box, per my answer, there is nothing dynamic per se. This is just vanilla auto layout, and the question appears to be a duplicate in that regard. – Chris Conover Sep 28 '14 at 22:37
  • You _must_ know it in advance. The content view's size is the scroll view's `contentSize`. If you don't provide this, the scroll view won't scroll. – matt Sep 28 '14 at 22:59
  • @evenro do not attempt to edit my answer to give _your_ answer. If you want to give a different answer, give a different answer! – matt Sep 28 '14 at 23:32
  • If you actually read what I edited - was just adding the code for doing what you said, for saving some time for those who want to implement it... but no problem - Added it on another answer. – evenro Sep 29 '14 at 00:06
  • Since when adding the code for doing what you recommended doing is defacing? I have not changed what you said, just implemented it (and since you didn't write how to implement what you recommended to, which is the whole idea of this website - code, and not architecture, I thought it would be a nice thing to do ... ) - but Np - removed the acceptance of your answer, and posted the code for it instead. – evenro Sep 29 '14 at 00:14
  • @evenro Welcome to Stack Overflow. Adding _your_ code to _my_ answer has always been defacing. My answer is mine. You may not modify it in a way that changes its content to something I didn't write. What you have gone on to do (supply your own answer) is perfectly legal. In fact, in a couple of days you can even accept your own answer! Alternatively, you could have edited your question to give the answer, but I like the way you did it better - it's an answer so it should be an answer. – matt Sep 29 '14 at 00:16
  • So why did they put the "Edit" button? if it's not for making answers better and more helpful for others I don't see any reason for it. – evenro Sep 29 '14 at 00:30
  • @matt, I might have misread your comment, but at least in general you don't strictly need to know the content size in advance, though (and perhaps what you meant) you do need a constraint. The distinction is that you can specify the content size via a relative width constraint to the parent SV with a multiplier of say 3.0, so that you always have 3 pages etc - you can use a multiplier instead of a hard constant (per my answer above). – Chris Conover Oct 01 '14 at 21:30
  • @chrisco Sure, I completely agree, obviously. I didn't say you had to know it as a fixed number. But you have to give it a value somehow if you want the scroll view to scroll, because the dimensions of this view are what is going to make the scroll view scrollable. As I say in my answers, you can for example generate the width and height through the sum of the constraints of its subviews - that is a number that you do not _personally_ know. But it's a form of knowing. But the OP is saying "No, I can't give this thing any width or height." – matt Oct 02 '14 at 01:04
  • @chrisco This is why I voted to close the question. It is not at all clear to me what kind of answer would satisfy the OP. I mean, we sent him two boats and helicopter and he's still waiting to be rescued? – matt Oct 02 '14 at 01:05
  • @matt - yeah, totally. And then he tried to commandeer the helicopter when you hovered with the rope. ;-) – Chris Conover Oct 02 '14 at 04:01
1

So, For solving this issue multiple things need to be done (as was discussed in the other answers, but without the kindness of giving the code for it by the other ppl):

  1. The scrollView should have constraints on its own to the edges of the screen.
  2. The objects within the inner UIView should have their own constraints.
  3. In code, add the constraints with the size you wish (No wonder why Microsoft development environment are much better.. never had to get to this sort of stuff for simple stuff).

The code is :

        // Change width
        var strConstraintWidth = "H:[contentView(==";
        strConstraintWidth = strConstraintWidth + UIScreen.mainScreen().bounds.width.description;
        strConstraintWidth = strConstraintWidth + ")]";

        let viewDictWidth = ["contentView":contentView];
        let widthConstraint:Array = NSLayoutConstraint.constraintsWithVisualFormat(strConstraintWidth, options: NSLayoutFormatOptions(0), metrics: nil, views: viewDictWidth);
        contentView.addConstraints(widthConstraint);

        // Check if Height constraint is necesarry
        let contentHeight = UIScreen.mainScreen().bounds.height - (adBanner.frame.size.height + 18.0);
        if (contentView.bounds.height < contentHeight)
        {
            var strConstraintHeight = "V:[contentView(==";
            strConstraintHeight = strConstraintHeight + contentHeight.description;
            strConstraintHeight = strConstraintHeight + ")]";

            let viewDictHeight = ["contentView":contentView];
            let heightConstraint:Array = NSLayoutConstraint.constraintsWithVisualFormat(strConstraintHeight, options: NSLayoutFormatOptions(0), metrics: nil, views: viewDictHeight);
            contentView.addConstraints(heightConstraint);
        }

        mainScrollView.contentSize = contentView.bounds.size;
evenro
  • 2,626
  • 20
  • 35
  • No code was given as at least from your question, no code was necessary - you could have done it with IB. – Chris Conover Oct 01 '14 at 21:18
  • Also, you are not supposed to directly set contentSize when using AL, and you are adding constraints without first removing the old ones, so if if the code is run during orientation changes, you will get duplicate / conflicting constraints. – Chris Conover Oct 01 '14 at 21:22
0

I can barely understand your question, but if you are asking how do you use auto layout in a scroll view, the answer is answered in multiple locations, from apple docs to SO, as a quick search would tell you:

The short version though is that you need to anchor the edges content view to the parent scrollview, and also set its height and width to match the parent scrollview. Ie. you need 6 constraints. Auto Layout is not an easy beast to tame, but this aspect does in fact work.

Edit: (per clarification in comment)

To affect the content size at the start or at a later time, you can either use the layout constraints for that dimension (either the width or height constraint), or (to my reading of the docs) by implementing intrinsicContentSize on the content view. Naturally the constraints can be larger than the intrinsic content size.

Note that it is generally easier to have a single content view to collect any sub content views, as this will give you easier control over sizing. By default, auto layout will calculate the effective content view size by (I believe) adding up the aforementioned intrinsic sizes of any immediate children of the scrollview, and it easier if you have a single container for any sub content views.

As an illustration, I had a graph view that I wanted to effectively span two pages, or device widths. I set the constraints to top, right, bottom, left, height, and then set the width to twice the main / scrollview width (that was itself screen width). So for my test width of 320, the content view width was 640 (minus margins etc). I set the 2x constraint by first using IB to create the default constraints, and then editing the multiplier property for the width constraint in the layout tab of the right-side inspector.

Community
  • 1
  • 1
Chris Conover
  • 8,889
  • 5
  • 52
  • 68
  • It is clear how to use AutoLayout within a view that is in the scrollView, it is also clear how to change the scrollView size to fit an area. The only thing that is not clear is how to change the size of the UIView which is the direct child of a scrollView. Let's say you have a UIView that its width is 320, I want it to stretch when it is being displayed on other devices. I know how to set the rules for it to stretch, and I know how to set the UIScrollView to stretch, but I don't know which constraint will make the UIView to do it. – evenro Sep 28 '14 at 21:41
  • In addition, all the code that I tried running, "setContentSize" initializing the frame to be of a specific size, are being ignored (in Xcode 6 ) – evenro Sep 28 '14 at 21:42
  • FWIW, It's easier to read with unambiguous references (contentView, parent scrollView, not "view" of which there are two, and when the thoughts are collected into linear paragraphs that don't circle back too much. The comment was more clear, the post is still less than coherent. – Chris Conover Sep 28 '14 at 22:39