In viewDidLoad, I instantiate a UIView and add a gradient layer to that UIView.
This works well on iPhone, but on iPad, UIView does not stretch out to fill the entire screen. Please note the following screenshot for iPad sim.
iPad simulator screenshot
I have attempted adding constraints both programmatically and by using XCode.
It seems that once I add the CAGradientLayer, the UIView does not conform to the constraints that I set, either programmatically or using XCode tools.
Sample Code:
gradientLayer = CAGradientLayer()
gradientLayer.frame = self.view.bounds
gradientLayer.locations = [0.5, 1.0]
gradient_View.backgroundColor = UIColor.blueColor()
let color1 = self.opus_Page_Background_Color.CGColor as CGColorRef
let color4 = self.opus_Page_Tertiary_Color.CGColor as CGColorRef
gradientLayer.colors = [color1, color4]
self.gradient_View.frame = self.view.bounds
self.gradient_View.layer.insertSublayer(gradientLayer, atIndex: 0)
gradient_View.translatesAutoresizingMaskIntoConstraints = false
let leadingConstraint = NSLayoutConstraint(item: gradient_View, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
leadingConstraint.active = true
view.addConstraint(leadingConstraint)
let trailingConstraint = NSLayoutConstraint(item: gradient_View, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
trailingConstraint.active = true
view.addConstraint(trailingConstraint)
let widthConstraint = NSLayoutConstraint(item: gradient_View, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 100)
view.addConstraint(widthConstraint)
let heightConstraint = NSLayoutConstraint(item: gradient_View, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 100)
view.addConstraint(heightConstraint)
NSLayoutConstraint.activateConstraints([leadingConstraint, trailingConstraint, widthConstraint, heightConstraint])
Try changing the last two constraints. Instead of matching width and height, pin it to Top & Bottom. The problem probably is that in viewDidLoad, your view has width = X, height = Y, but that's not the final layout.
If that does not work, try adding it in viewDidLayoutSubviews.
Hope it helps!
You have added leading and trailing constraint which means you have got the width of the view. So there is no need to add width constraint at all. Remove width from storyboard or programmatically which ever you are using.
Also i could see a missing top constrai nt. Resolve that also
Related
i'm not very familiar with autolay-out and constraints.
I have build a view with 7 subviews which are build with constraints to fit landscape and portait mode. Everything is fine (see picture).
Here under a sample code used for the 6th subview.
The width constraint has mediumPriority and the others (left, top, bottom) have highPriority.
6View = UIView()
mainScrollView.addSubview(6View)
6View.backgroundColor = UIColor(red: 120/255, green: 120/255, blue: 120/255, alpha: 1.0)
6View.translatesAutoresizingMaskIntoConstraints = false
// constraints
let topConstraint = NSLayoutConstraint(item: 6View, attribute: .top, relatedBy: .equal, toItem: mainScrollView, attribute: .top, multiplier: 1, constant: kMainMargin)
topConstraint.priority = highContraintPriority
mainScrollView.addConstraint(topConstraint)
let leftConstraint = NSLayoutConstraint(item: 6View, attribute: .left, relatedBy: .equal, toItem: day5View, attribute: .right, multiplier: 1, constant: kMainMargin)
leftConstraint.priority = highContraintPriority
mainScrollView.addConstraint(leftConstraint)
let bottomConstraint = NSLayoutConstraint(item: 6View, attribute: .bottom, relatedBy: .equal, toItem: mainScrollView, attribute: .bottom, multiplier: 1, constant: kMainMargin)
bottomConstraint.priority = highContraintPriority
mainScrollView.addConstraint(bottomConstraint)
let widthConstraint = NSLayoutConstraint(item: 6View, attribute: .width, relatedBy: .equal, toItem: mainScrollView, attribute: .width, multiplier: (1/7), constant: -1)
widthConstraint.priority = mediumContraintPriority
mainScrollView.addConstraint(widthConstraint)
Now i'd like when i touch any of the 7 views to see the touched view to expand (double size) and the other 6 views to collapse.
How would you achieve this ?
Thanks a lot for your help.
Best regards.
Make a reference to the width constraint for every view and when clicked do
widthConstraint.constant = // expanded value
and set this for all the other views
otherwidthConstraint.constant = 0
then call
self.view.layoutIfNeeded()
You may also put all these constraints inside an array ( var arrOfAllWidths = [NSLayoutConstraint]()) and do this
arrOfAllWidths.forEach { $0.constant = 0 }
then get the index of the clicked view say it's view 0
arrOfAllWidths[0].constant = // expanded value
Also no need for the priorities , and don't forget to set this when give constraints to a view programmatically
view6.translatesAutoresizingMaskIntoConstraints = false
I have an UITableView with custom cells. The structure of every cell is like that: I have contentView, in this contentView I have backView (simple UIView with white background and cornered radius 16.0), in this backView I have an imageView with some picture.
What I want is to have this imageView cornered (within his parent UIView — backView — borders). And it doesn't work this way.
The code is quite simple (from ImageCell.swift):
self.backView = UIView()
self.backView.backgroundColor = UIColor.white
self.backView.translatesAutoresizingMaskIntoConstraints = false
self.backView.layer.cornerRadius = 16.0
self.contentView.addSubview(backView)
self.picture = UIImageView()
self.picture.translatesAutoresizingMaskIntoConstraints = false
self.picture.contentMode = UIViewContentMode.scaleAspectFill
self.picture.backgroundColor = UIColor.gray
self.picture.clipsToBounds = true
self.backView.addSubview(picture)
let constraintPicTop = NSLayoutConstraint(item: picture, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .topMargin, multiplier: 1.0, constant: -6)
let constraintPicLeft = NSLayoutConstraint(item: picture, attribute: .left, relatedBy: .equal, toItem: backView, attribute: .leftMargin, multiplier: 1.0, constant: -8)
let constraintPicRight = NSLayoutConstraint(item: picture, attribute: .right, relatedBy: .equal, toItem: backView, attribute: .rightMargin, multiplier: 1.0, constant: 8)
constraintBottomPic = NSLayoutConstraint(item: picture, attribute: .bottom, relatedBy: .lessThanOrEqual, toItem: contentView, attribute: .topMargin, multiplier: 1.0, constant: 150)
I don't know the size of the image beforehand, so constraintBottomPic value is updating in cellForRowAt function.
And it's working except this image is not cornered (and I believe it should be).
(It's not possible for me to set cornerRadius for UIImageView unfortunately).
update: Found the solution. It seems I had to set 'clipsToBounds' to true in all the parent views directly (contentView and backView, in my case).
You should set the clipsToBounds property of the higher level container view (like the contentView of your cell.)
Apply imageView.layer.maskToBounds = YES;
Apply this to view or imageview on which you want to set corner radius.
As you have mentioned corner radius to your view you need to set this for your view
I have added a UIView to a table cell through my storyboard with the following constraints:
Then I have the following code to programmatically add a UIImageView to the UIView above and size it according to the orientation of the screen.
//Use half the screen size width when on an iPhone and on Landscape
let image: UIImage = UIImage(named: HEADER_IMAGE_BATH)!
imageView = UIImageView(image: image)
imageView!.frame = CGRectMake(0 , 0, self.view.frame.width / 2, 185)
imageView!.contentMode = .ScaleAspectFit
//center image
let centerXConst = NSLayoutConstraint(item: imageView!, attribute: .CenterX, relatedBy: .Equal, toItem: imageWrapperView, attribute: .CenterX, multiplier: 1, constant: 1)
let centerYConst = NSLayoutConstraint(item: imageView!, attribute: .CenterY, relatedBy: .Equal, toItem: imageWrapperView, attribute: .CenterY, multiplier: 1, constant: 1)
NSLayoutConstraint.activateConstraints([centerXConst, centerYConst])
//add to sub view
imageWrapperView.addSubview(imageView!)
However, my image does not get centered when in landscape. My image is only half the width of the screen and I would like to center it inside my UIView. What am I missing? Thanks
You should use Auto Layout instead of frame for width and height of imageView
You have to add imageView to imageWrapperView before add constraints
You have to set imageView.translatesAutoresizingMaskIntoConstraints to false
Then, the final code is:
//Use half the screen size width when on an iPhone and on Landscape
let image: UIImage = UIImage(named: "key.png")!
let imageView = UIImageView(image: image)
imageView.contentMode = .ScaleAspectFit
imageView.translatesAutoresizingMaskIntoConstraints = false
//add to sub view
imageWrapperView.addSubview(imageView)
//center image
let centerXConst = NSLayoutConstraint(item: imageView, attribute: .CenterX, relatedBy: .Equal, toItem: imageWrapperView, attribute: .CenterX, multiplier: 1.0, constant: 0.0)
let centerYConst = NSLayoutConstraint(item: imageView, attribute: .CenterY, relatedBy: .Equal, toItem: imageWrapperView, attribute: .CenterY, multiplier: 1.0, constant: 0.0)
let heightConstraint = NSLayoutConstraint(item: imageView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 185.0)
let widthConstraint = NSLayoutConstraint(item: imageView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: self.view.frame.width / 2)
imageView.addConstraints([heightConstraint, widthConstraint])
NSLayoutConstraint.activateConstraints([centerXConst, centerYConst])
When you're using autolayout, do not try to change the frame of the views. If you need to change the frame, better take the outlets of the constraints and change them programatically.
In your question, to center align the imageView, you can do it by putting 4 constraints. Set the height and width of the imageView and the other two are center horizontally and center vertically constraints.
This is the basic way of center aligning any type of view.
I have a parent, called infoView. It has two children: subLabel and tinyImageView. I'd like both of these children to be size 30.0, with subLabel first, followed by 10 pixel padding, followed by the tinyImageView.
For some reason, my tinyImageView is not respecting ANY of the constraints I put below. Even the height/width is not respected.
let boxSize = infoView.frame.size.height //30
let subLabel = UILabel()
subLabel.frame = CGRectMake(0, 0, boxSize, boxSize)
subLabel.layer.cornerRadius = 5.0
subLabel.clipsToBounds = true
subLabel.backgroundColor = logoColor(1)
subLabel.text = String(post.subscribers)
subLabel.font = UIFont(name: "Lato-Bold", size: 13.0)
subLabel.textColor = UIColor.whiteColor()
subLabel.textAlignment = .Center
infoView.addSubview(subLabel)
//Image
let tinyImageView = UIImageView(image:UIImage(named: "MO.jpg"))
tinyImageView.layer.cornerRadius = 2.5
tinyImageView.clipsToBounds = true
infoView.addSubview(tinyImageView)
let widthConstraint = NSLayoutConstraint(item: tinyImageView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: boxSize)
tinyImageView.addConstraint(widthConstraint)
let heightConstraint = NSLayoutConstraint(item: tinyImageView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: boxSize)
tinyImageView.addConstraint(heightConstraint)
print("------------")
let horizontalConstraint = NSLayoutConstraint(item: subLabel, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: tinyImageView, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 10)
infoView.addConstraint(horizontalConstraint)
let verticalConstraint = NSLayoutConstraint(item: subLabel, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: tinyImageView, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)
verticalConstraint.active = true
The image turns out way too big, and the horizontal/vertical constraints don't work at all. Currently, the image overlaps subLabel, as if it was just added without any constraints.
As #Paulw11 stated in the comments, you need to set translatesAutoResizingMaskIntoConstraints to false for programmatically created views. Also, your constraints will resize the frame for your UIImageView, but they won't scale the image. For that, you need to set the contentMode property:
tinyImageView.translatesAutoResizingMaskIntoConstraints = false
tinyImageView.contentMode = .ScaleToFill
Values you probably want to consider for contentMode are .ScaleToFill (scale to fit area distorting aspect ratio if necessary), .ScaleAspectFit (maintain aspect ratio and leave part of the view as transparent if necessary) and .ScaleAspectFill (maintain aspect ratio and clip part of image if necessary).
From your code, I just saw one activation for constraint verticalConstraint.
active all the constraints you add.
if your constraints got conflicted,
Set translatesAutoResizingMaskIntoConstraints to false(usually if you set constraints programmatically, you set it to false)
I have a UIButton inside a UIView, my UIButton has constraints which I set in storyboard. Now, I want to set the center of the UIButton at the center of the UIView. How will I do that programmatically?
Try .center property like
myButton.center = self.view.center
You can also specify x and y If you need.
myButton.center.x = self.view.center.x // for horizontal
myButton.center.y = self.view.center.y // for vertical
This approach is using Using NSLayoutConstraint where self.cenBut is the IBoutlet for your button.
func setupConstraints() {
let centerX = NSLayoutConstraint(item: self.cenBut, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
let centerY = NSLayoutConstraint(item: self.cenBut, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)
let height = NSLayoutConstraint(item: self.cenBut, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 22)
self.cenBut.translatesAutoresizingMaskIntoConstraints = false
self.view.addConstraints([centerX, centerY, height])
}
In viewDidLoad()
self.view.removeConstraints(self.view.constraints)
self.setupConstraints()
since you are using constraints, you won't be able to set the center so you need to use constraints to set the center as well:
let centerYCon = NSLayoutConstraint(item: labelMessage,
attribute: .CenterY,
relatedBy: .Equal,
toItem: contentView,
attribute: .CenterY,
multiplier: 1.0,
constant: 0.0);
contentView.addConstraint(centerYCon);
let centerXCon = NSLayoutConstraint(item: labelMessage,
attribute: .CenterX,
relatedBy: .Equal,
toItem: contentView,
attribute: .CenterX,
multiplier: 1.0,
constant: 0.0);
contentView.addConstraint(centerXCon);
I'm assuming that you know what "programmatically" means with autolayout constraints. If you are truly using autolayout then you must have set the properties of your button to setTranslatesAutoresizingMaskIntoConstraints to false.
This can be done in 2 ways:
myButton.center = view.center //view is your parentView
myButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
I should be
yourButton.setCenter(self.view.center);
But keep in mind that if you programmatically set the frame of a view, your layout constraints might not work as intended.