Reputation: 19572
Inside IB I have a viewController with a segmentedControl and 2 containerViews. In each containerView I have a tableView. From each tableView I push on a detailView. My auto layout is in IB.
Once I pick a segment, I see the corresponding tableView, I pick a cell and the correct detailView gets pushed on the scene.
The issue is once the detailView gets pushed on the segmentedControl is still visible. I decided to hide the segmentedControl which works but there is a big empty space there. I tried to programmatically increase the size of detailView's view but it's not expanding. From what I read it's because I made the initial constraints in storyboards.
How to I programmatically get the detailView's view to expand?
code:
DetailViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
//this isn't increasing the view's size
self.view.frame.size.height += 20.0
//doesn't work. I get an error on the last argument
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height += 20.0)
//doesn't work. I get an error on the last argument
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.size.height += 20.0)
}
}
Errors:
//Error for the last argument- height: *self.view.frame.height += 20.0*
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height += 20.0)
Left side of mutating operator isn't mutable: 'height' is a get-only property
//Error for the last argument- *self.view.frame.size.height += 20.0*:
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.size.height += 20.0)
Cannot invoke initializer for type 'CGRect' with an argument list of type '(x: Int, y: Int, width: CGFloat, height: ())'
Upvotes: 36
Views: 130382
Reputation: 1
Use of size classes in this case because effective way to handle the size of the screen in the different layout , and good for the command for ios
Upvotes: -2
Reputation: 4765
Remove the constraints first. I had constraints in the interface builder, and repositioning worked, and I didn't understand why size changes won't apply. So avoid constraints when manually change the size of a view.
Upvotes: 0
Reputation: 3306
For me, a programmatic solution wouldn't require me to create an outlet for every height constraint I might want to modify. Here's a code-only solution that works nicely for me. It should work whether the original constraint was created on the storyboard or programmatically. It also provides an option to animate the change if desired -- although I'm not sure if this would work if the view is nested in a complex hierarchy.
extension UIView {
func setHeight(_ h:CGFloat, animateTime:TimeInterval?=nil) {
if let c = self.constraints.first(where: { $0.firstAttribute == .height && $0.relation == .equal }) {
c.constant = CGFloat(h)
if let animateTime = animateTime {
UIView.animate(withDuration: animateTime, animations:{
self.superview?.layoutIfNeeded()
})
}
else {
self.superview?.layoutIfNeeded()
}
}
}
}
Upvotes: 12
Reputation: 1693
Swift 4.2
I create an example for you programmatically:
var flowHeightConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(button)
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
button.widthAnchor.constraint(equalToConstant: 100).isActive = true
flowHeightConstraint = button.heightAnchor.constraint(equalToConstant: 30)
flowHeightConstraint?.isActive = true
}
@objc func animateButtonTapped() {
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseOut, animations: {
self.flowHeightConstraint?.constant = 100
self.view.layoutIfNeeded()
}, completion: nil)
}
lazy var button: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .green
button.addTarget(self, action: #selector(animateButtonTapped), for: .touchUpInside)
return button
}()
this line of code create a button an on tapped change height of button with animation.
hope this help :)
Upvotes: 9
Reputation: 1235
You need to create an outlet for the height constraint of the detail view, and then you can adjust the height programmatically like this myHeightConstraint.constant += extraHeight
where extraHeight
is a number indicating how much taller you want the detail view to be. You also may need to call self.view.layoutIfNeeded()
afterwards.
To create an outlet from a constraint, control drag from the constraint in the storyboard editor (just like you would for an outlet of a UIView) into your code.
You are right - because you are using auto layout and constraints, the adjustments need to be made with constraints too. Setting the raw frames can lead to unexpected behavior. Let me know if you have any other questions or difficulties.
Upvotes: 54
Reputation: 318774
Inside the CGRect
initializer you should not be using +=
, just +
.
Change:
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height += 20.0)
to:
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height + 20.0)
You should not be trying to change the value of self.view.frame.height
inside the initializer.
Upvotes: 19