IOS - Pure AutoLayout and UIScrollView not scrolling
This is my first time using UIScrollViews with a pure Autolayout approach. This is what the view hierarchy looks like
view
-scrollview
--view1
--view2
--view3
scrollview must contain view1 | view2 | view3 in that order.
I have set the scroll width, height, center and bottom space for the view. The created objects view1, view2 and view3 have their own width and height constraints in the updateConstraints method. Additionally, some restrictions are provided in the code. For what reason is this scrolling not scrolling from left to right? I have read literally every tutorial I can find on the internet about creating and adding subroutines to a UIScrollView programmatically with auto layout. I found some mention of providing four different constraints: leading, trailing, top and bottom for each view added as a subview to the scrollview. Are these the only NSLayoutAttributes that can be specified? How are attributes related,such as NSLayoutAttribueLeft or NSLayoutAttribueRight? I also read the documentation on the Apple website, namelyhttps://developer.apple.com/library/ios/technotes/tn2154/_index.html . I have the setup I currently have. Everything is done with code.
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataSource = @[ [[PCCGenericRating alloc] initWithTitle:@"Easiness"
andMessage:@"WHAT A JOKERRRR"
andVariatons:@[ @"very easy", @"easy", @"moderate", @"hard", @"very hard"]],
[[PCCGenericRating alloc] initWithTitle:@"Joker"
andMessage:@"WHAT A JOKERRRR"
andVariatons:@[ @"very easy", @"easy", @"moderate", @"hard", @"very hard"]],
[[PCCGenericRating alloc] initWithTitle:@"Difficulty"
andMessage:@"YOu are not difficult at all"
andVariatons:@[ @"very easy", @"easy", @"moderate", @"hard", @"very hard"]]
];
[self initView];
}
- (void)initView {
CGFloat navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
CGFloat heightDifference = navigationBarHeight + statusBarHeight;
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.delegate = self;
[self.scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
self.scrollView.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.scrollView];
//setup constraints
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeHeight
multiplier:1.0f
constant:-heightDifference]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0f
constant:0.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0f
constant:0.0]];
[self.dataSource enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PCCGenericRating *rating = (PCCGenericRating *)obj;
PCCGenericRatingView *ratingView = [self createViewWithRating:rating];
[self.scrollView addSubview:ratingView];
int multiplier = (idx == 0) ? 1 : (int) (idx + 1) ;
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:ratingView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeCenterX
multiplier:multiplier
constant:0.0f]];
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:ratingView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.scrollView
attribute:NSLayoutAttributeCenterY
multiplier:1.0f
constant:0.0f]];
}];
}
- (PCCGenericRatingView *)createViewWithRating:(PCCGenericRating *)rating {
PCCGenericRatingView *view = [PCCGenericRatingView genericRatingViewWithTitle:rating.title andMessage:rating.message];
return view;
}
After printing the scrollview constraints, they look good to me:
po self.scrollView.constraints
<__NSArrayM 0x115b051f0>(
<NSLayoutConstraint:0x1145d9290 PCCGenericRatingView:0x114579880.centerX == UIScrollView:0x11458d4b0.centerX>,
<NSLayoutConstraint:0x1145d9410 PCCGenericRatingView:0x114579880.centerY == UIScrollView:0x11458d4b0.centerY>,
<NSLayoutConstraint:0x1145d9dd0 PCCGenericRatingView:0x1145d9560.centerX == 2*UIScrollView:0x11458d4b0.centerX>,
<NSLayoutConstraint:0x1145d9e40 PCCGenericRatingView:0x1145d9560.centerY == UIScrollView:0x11458d4b0.centerY>,
<NSLayoutConstraint:0x1145da6b0 PCCGenericRatingView:0x1145d9e90.centerX == 3*UIScrollView:0x11458d4b0.centerX>,
<NSLayoutConstraint:0x1145da730 PCCGenericRatingView:0x1145d9e90.centerY == UIScrollView:0x11458d4b0.centerY>
)
Here's a screenshot of what it looks like:
It seems strange to me that the last item in the data source is the first view controller to show in the scrollview when it should be the last view. It also doesn't scroll left-right as it should.
source to share
When you are printing your constraints try printing scrollview.contentSize, it will probably be 0,0 and that is where your problem is. As far as I know, and as you mentioned in your post, you must explicitly set the subviews of the scrollview to the top-bottom left and right constraints of the scrollviews. In doing so, they automatically set the contentSize of the scroll, which will allow it to scroll. It looks like you are only setting the X and centerY center constraints which will not set the scrollviews contentSize for what you need.
Try to install them programmatically (this is pseudocode, but you get the idea):
- view1.topConstraint = scrollView.topConstraint
- view1.leftConstraint = scrollView.leftConstraint
- view3.bottomConstraint = scrollView.bottomConstraint
- view3.rightConstraint = scrollView.rightConstraint
If you set it all up correctly, your scroll will scroll correctly. Just remember to check the content, and if the content is 0.0 your limits will not be configured correctly.
source to share