Add Constraint to ScrollView - ios

I am trying to add constraints to UIScrollView with a label (subview of scrollview)
but the scrollview wouldn't scroll and trailing never work.
float y = self.navigationController.navigationBar.frame.size.height + 30;
self.scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0,0, 0,0)];
[self.scrollView setBackgroundColor:[UIColor blueColor]];
[self.scrollView setScrollEnabled:YES];
[transparentImageView addSubview:self.scrollView];
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[transparentImageView addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:transparentImageView attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-120.0]];
//leading
[transparentImageView addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:transparentImageView attribute:NSLayoutAttributeLeading multiplier:1.0f constant:20.0f]];
//trailing
[transparentImageView addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:transparentImageView attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:-20.0]];
[transparentImageView addConstraint:[NSLayoutConstraint constraintWithItem:self.scrollView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:transparentImageView attribute:NSLayoutAttributeTop multiplier:1.0f constant:y]];
self.shineText = [[RQShineLabel alloc]initWithFrame:CGRectMake(0,0, 0, 0)];
[self setupText];
[self.shineText setBackgroundColor:[UIColor redColor]];
[self.scrollView addSubview:self.shineText];
self.shineText.translatesAutoresizingMaskIntoConstraints = NO;
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, self.scrollView.frame.size.height);
//bottom
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:self.shineText attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.scrollView attribute:NSLayoutAttributeBottom multiplier:1.0f constant:-10.0f]];
//leading
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:self.shineText attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.scrollView attribute:NSLayoutAttributeLeading multiplier:1.0f constant:10.0f]];
//trailing
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:self.shineText attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.scrollView attribute:NSLayoutAttributeTrailing multiplier:1.0f constant:-500.0f]];
[self.scrollView addConstraint:[NSLayoutConstraint constraintWithItem:self.shineText attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.scrollView attribute:NSLayoutAttributeTop multiplier:1.0f constant:20]];

If you have this line self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, self.scrollView.frame.size.height); then your scroll view never make scroll at all because your content size is the same as the scroller frame, the content size of your scrollView must be greater than the scrollView frame in order to scroll
Try with something like this
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, 1000);
then your scrollView must scroll
I hope this helps you

Generally, while working with UIScrollView and auto layouts, we need to add one UIView as child view on scroll view with same size as scroll view.
Here is tutorial which explains this in details.
But this tutorial is for using scroll view in .nib file.
For adding scroll view programatically, go through Apple developer technical note.
It suggest that:
Use constraints to lay out the subviews within the scroll view, being sure that the constraints tie to all four edges of the scroll view and do not rely on the scroll view to get their size.

try this tricky way to work with scrollview in storyboard. I created a small video tutorial to show how easy to work with scroll view. You should have a small knowledge of autolayout.
step 1 : change your viewcontroller size as your need
step 2 : add a scroll view and setup constarints (top, lead, trail and top) to the conatainer view.
step 3 : then add another view on to scroll view(this is your child view where you add your all other IBOutlets)
step 4 : then add constraints to it. (top, lead, trail and top to scroll view) + (width and height to it self)
step 5 : create an outlet to the child view width to your controller and give the width programatically( the device width)
this small tutorial shows you how to do it..
part one : less thant 5 min
part two : less than 5 min
hope this will help to you.

Related

iOS Custom Keyboard Extension Autolayout

I'm developing a custom keyboard and i want to use only a UICollectionView as content. The CollectionView should fill (center x and y, width and height available space) of the keyboardview.
My problem is that if i rotate the device the collection view won't be resized.
I tried layout constraints, resizing the view on viewWillTransitionToSize but it does not work. Can anyone give me a hint or show me a way to get this done?
Autolayout should set translatesAutoresizingMaskIntoConstraints to NO before adding Constraint. The code below can make a UICollectionView autolayout with equal edges.
- (void)viewDidLoad {
[super viewDidLoad];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
collectionView.translatesAutoresizingMaskIntoConstraints = NO;
collectionView.backgroundColor = [UIColor redColor];
[self.view addSubview:collectionView];
//Adding layout constraint
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:collectionView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:collectionView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:collectionView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:collectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0]];
}
In addition, I recommend you to use Masonry to build autolayout. In your case, you just need to run the code below to make constraints.
[collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
By the way, autolayout will use more memory then calculating frame yourself. As iOS Keyboard extension has a very harsh memory usage limit (around 40mb depends on your device). If your keyboard would use many memory on process other things, I suggest you don't use autolayout.

Subview visible but frame outside superview frame

I have a parent VC that loads a child VC inside it. Code in parent VC is as follows:
self.draggerViewController = [[DraggerViewController alloc] initWithSuperView:self.view];
And the code of the child VC is as follows:
- (instancetype)initWithSuperView:(UIView*)superView {
self = [super init];
if (self) {
self.superView = superView;
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
[superView addSubview:self.view];
[superView addConstraint:[NSLayoutConstraint constraintWithItem:superView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1 constant:0]];
[superView addConstraint:[NSLayoutConstraint constraintWithItem:superView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]];
self.constraintDraggerAttributeBottom = [NSLayoutConstraint constraintWithItem:superView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
[superView addConstraint:self.constraintDraggerAttributeBottom];
}
return self;
}
With this code, the subview is visible on its parent view and constraints are applied correctly so that it is placed at the bottom of the parent view with leading and trailing being 0. BUT, the real frame of the view is outside the parent view.
That is, I can see the subview at the bottom of the parent view but the frame of this subview is frame = (0 -315; 768 35).
If I set 'clipToBounds' to 'YES', the view is placed on the real frame but now constraints are not applied correctly.
How can I place this child VC inside the parent VC's view at the position I want using constraints?
Thank you!
OK, got it...
I was forgetting the height constraint of the view... What a shame...
[superView addConstraint:[NSLayoutConstraint constraintWithItem:superView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:1 constant:0]];
Thank you all!
Try this :
superView.insertSubview(self.view, at: self. superView.subviews.count)

How to make equal space b/w UIFields using auto-layouts?

I am a beginner with iOS auto-layouts and I am adding five labels on my view controller and so for every thing is OK. (Here five labels width and heights are constant.)
My main requirement is how to make equal horizontal spacing b/w that five labels. I can set middle label and left and right corner labels and they are perfect. But I don't understand how to add second left and second right labels, and how to make equal space B/W them, as like another labels?
My requirement is exact like below image, please help me.
My code:
#import "ViewController2.h"
#interface ViewController2 ()
{
UILabel * left1;
UILabel * left2;
UILabel * middle;
UILabel * right1;
UILabel * right2;
}
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
left1 = [[UILabel alloc] init];
left1.backgroundColor = [UIColor grayColor];
left1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:left1];
left2 = [[UILabel alloc] init];
left2.backgroundColor = [UIColor grayColor];
left2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:left2];
middle = [[UILabel alloc] init];
middle.backgroundColor = [UIColor grayColor];
middle.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:middle];
right1 = [[UILabel alloc] init];
right1.backgroundColor = [UIColor grayColor];
right1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:right1];
right2 = [[UILabel alloc] init];
right2.backgroundColor = [UIColor grayColor];
right2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:right2];
//Applying autolayouts for middle lable
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:middle
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:100]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:middle
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:10]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:middle
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:1.0
constant:50]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:middle
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:1.0
constant:20]];
//Appying autolayouts for left1 labe1
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:left1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:100]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:left1
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:10]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:left1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:1.0
constant:50]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:left1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:1.0
constant:20]];
//Appying autolayouts for right1 labe1
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:right1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:100]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:right1
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:-10]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:right1
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:1.0
constant:50]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:right1
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:1.0
constant:20]];
}
#end
Here is steps for you (via IB)
Create your 5 labels
Setup left and right label constraints (for left - leading, top, width, height; for right - trailing, top, width height)
Center horisontally middle label (top constraint, width, height, center horisontally)
Here is some trick - add two container views between left and middle label + middle label and right label
setup constraints for this containers ( leading and trailing constraints + top + height) This containers will be flexible depend on screen size
after adding constraints it should looks like
The last step - place other labels into green container and setup constraints as for middle label ( it should be centered in container + add top , width , height constraint )
All constraints provided at the left size, so you can easily recreate it via code, if you need
Hope this helps
So I know your question was answered, but in iOS9 there are UIStackViews which are specifically built for this situation. Here's how to use them for future reference:
Shift + click and drag to select all your labels (note you don't have to size them)
Click the StackView button on the bottom right of the screen
Then select your StackView and set Alignment to "Fill", and Distribution to "Equal Spacing"
Then with your stackview still selected click the pin icon, and put 200 at the top, 10 and 10 for the sides, and 130 for the height. Then click add 4 constraints.
Finally click the triangle icon and select update frames.
Voila! You have your layout without having to use spacers!

Facebook Audience Network ios FBAdView width

I added a FBAdView to a UIView in the view controller.
(I set the view background to red)
the FBAdView was created with adSize of kFBAdSizeHeight50Banner.
The problem is that the FBAdView calculates its width when it is being added, but after rotating the device it doesn't calculate its width again
I tried using autolayout but it didn't work
code for adding the FBAdview (Adding to UILabel with red backgroud)
FBAdView *fbAdView = [[FBAdView alloc] initWithPlacementID:#"***************_***************"
adSize:kFBAdSizeHeight50Banner
rootViewController:self];
fbAdView.delegate = self;
[fbAdView loadAd];
[self.banner addSubview:fbAdView];
code for autolayout - doesn't work
// Width constraint, parent view width
[self.banner addConstraint:[NSLayoutConstraint constraintWithItem:fbAdView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.banner
attribute:NSLayoutAttributeWidth
multiplier:1
constant:0]];
// Height constraint, parent view height
[self.banner addConstraint:[NSLayoutConstraint constraintWithItem:fbAdView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.banner
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0]];
// Center horizontally
[self.banner addConstraint:[NSLayoutConstraint constraintWithItem:fbAdView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.banner
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
// Center vertically
[self.banner addConstraint:[NSLayoutConstraint constraintWithItem:fbAdView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.banner
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0]];
print screen
when the banner is added it fit the screen width
after rotating it doesn't change its width (like its parent red view)
I think you're missing some constraints.
Adding these lines (might need some minor changes) makes your code work:
self.banner.translatesAutoresizingMaskIntoConstraints = NO;
fbAdView.translatesAutoresizingMaskIntoConstraints = NO;
// Width constraint
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.banner
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:1
constant:0]];
// Height constraint
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[banner(==50)]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(banner)]];
I've posted a sample project at https://github.com/overlordnyaldee/BannerAutoLayout

Constraints for subview not working in iOS 8, XCode 6 (6A313). Works iOS 7

Simply adding a subview UIView from a controller creating using instantiateViewControllerWithIdentifier to the current controllers view and adding constraints to maintain the size of the new subview to cover the entire area. The code below worked in iOS 7. iOS 8 sizes the subview to a small portion of the upper left corner. iOS 7 does what I expect, which is to size the subview across the entire size of the parent view. I'd attach an image, but don't have the rep for that. Setting translatesAutoresizingMaskIntoConstraints to YES fixes the issue, but then the view does not honor the constraints and resize when orientation changes or sizing changes.
spotCheckStoresViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"visitStoresViewController"];
spotCheckStoresViewController.mainViewController = self;
spotCheckStoresViewController.dataMode = kDataModeViews;
spotCheckStoresViewController.lastRow = [self getViewsLastRow];
spotCheckStoresViewController.view.tag = -200;
currentView = spotCheckStoresViewController.view;
[self addChildViewController:spotCheckStoresViewController];
[self.view insertSubview:currentView belowSubview:_menuViewController.view];
currentView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:currentView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:currentView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:currentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:currentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
//[self.view updateConstraints];
//[self.view layoutIfNeeded];
I've tried setting the frame of the subview as well. Any ideas what might have changed in iOS 8 to alter the behavior of constraints used in this way?
In my case, the problem related to constraints labeled UIView-Encapsulated-Layout-Width and UIView-Encapsulated-Layout-Height. When I removed them, everything behaved as though my view was of zero size, with everything centered on the upper left corner of the screen. When I left them in, new constraints worked as expected. I also retained the constraints labeled _UILayoutSupportConstraint.
In my case, it was only happening on iOS 8.3. There was a conflict with existing constraints. A colleague found that I needed to first remove any existing constraints before adding the others.
[self.view removeConstraints:self.constraints];

Resources