why can't change button height when set frame? - ios

I am testing a sample project with an button . And I write this , but it can't change the button's height .
What's wrong?
class ViewController: UIViewController {
#IBOutlet var test: UIButton!
override func loadView() {
super.loadView()
var newFrame = test.frame
newFrame.size = CGSizeMake(newFrame.width, newFrame.height * 10)
test.frame = newFrame
}
}
And get the same height I set .

Put your code in
viewDidLayoutSubviews
After calling super. Theoretically you need to wait for the auto layout engine to be done before you modify the frame, otherwise it will be set for you. In this case this is probably what happens as on didLoad the autolayout might not be done yet.
Instead of setting the frame, set the constraints for the button. This way you have full control. Especially when you layout other controls along with your button. Makes your life easier. Mostly.
For your reference check the wwdc sessions about auto layout and adaptive ui.
Hope this helps.

Related

Custom UITableView Cell's Stack View Cannot Detect Super View Dimension

Context I have a UITableViewController with custom cells designed in a .xib file. In that .xib file I'm trying to set dynamic widths so splits the cell width into three subviews.
Problem is that the cell doesn't seem to be able to get the proper width, causing the cell to not fill the entire width. Here's a picture to better illustrate what I'm saying.
cell_not_filling_width
My Understanding (Could be totally misunderstanding this) Setting the frame constraint in the .xib file is no good b/c the program won't know the width until runtime. In other words, awakeFromNib (1.) loads before the screen width is determined... So idk how to fix this problem.. Any guidance would be greatly appreciated.
Presumably this is where the width is set - the width on my interface builder when I'm looking at the .xib file is the same when I print it out at cellForRowAt
Notes In my viewDidLoad function I've registered the nibfile as such so I don't think that's the problem. tableView.register(UINib(nibName: "NewTableViewCell", bundle: nil) , forCellReuseIdentifier: "newTableViewCell").
Here is some code that could be relevant.
NewTableViewCell.swift
import UIKit
class NewTableViewCell: UITableViewCell {
#IBOutlet var typeLabel: UILabel!
#IBOutlet var timeLabel: UILabel!
#IBOutlet var completedLabel: UILabel!
#IBOutlet var correctLabel: UILabel!
#IBOutlet var parentView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
The parentView is a view that contains the three subviews.
Here'sa picture of the .xib file
Here's a picture of my constraints on the .xib file (it seems cluttered)
UPDATE
Tried the stack view approach: XCode just defines the width as the subview with the biggest width (according to how large the text is)
Here is a picture of the current situation and the current constraints
I figured the constraints on the label may also be relevant:
UPDATE2
Ok I think I've found the problem; Basically the stack view cannot seem to detect the super view's length and width and it's dimension.
NOTE I have edited the constraints.
Here is what it looks like if I set the width and height to a constant value. The stack view will actually go to the set constraints
Here is what it looks like if I take those constraints out. So it seems like the width and height are 0. Which is why I believe the constraints are not being adopted from the super view.
Does anyone know how to fix this?
Try the below code in cellforRow.
Add IBOutliet for stackviewWidth and set is dynamically as shown below. Also check if the cell goes to the full width of the device by adding background color to cell.
if let appDelegate = UIApplication.shared.delegate as? AppDelegate,
let window = appDelegate.window {
cell.stackViewWidthConstraint = window.bounds.width
}

Make use of safe areas in Objective C

I am working to migrate my app so I can use it on iPhoneX without scaling. Currently I layout a subview with the following code:
CGRect frame = self.view.bounds;
frame.size.height = 295;
frame.origin.y = 20;
This works fine until you add in the notch. I am not seeing a clear way to find out what the frame.origin.y should be set to, without just hard coding.. Which I would like to avoid.
What I would like to do is this - frame.origin.y = 20 + self.view.safeAreaInserts.top
But that doesn't do a thing.
Thanks!
Perhaps safeAreaInsets is being changed after your code runs (for example if you're trying to perform layout in viewDidLoad). You need to override safeAreaInsetsDidChange to be notified when it changes.
Note that safeAreaInsetsDidChange is a method of UIView, not UIViewController, so you'll need to create and use a subclass of UIView to override the method. It would probably be sufficient to override it like this:
override func safeAreaInsetsDidChange() {
super.safeAreaInsetsDidChange()
setNeedsLayout()
}
And then you can set the subview's frame in layoutSubviews.
Or you could just use constraints instead of setting the frame directly, and let auto layout handle it all for you.

Changing an Autolayout-constrained UIView's frame at runtime in Swift

For example, I use this code to change the frame position of a UIView called Propo:
self.Propo.frame.origin.x -= self.view.frame.width
(Propo has constraints in Storyboard)
But When the app view disappears and reappears, the UIView resets itself to its original position. How can I do to resolve it? I want the UIView to keep its position when I change it programmatically.
I've tried updateViewConstraints() by anything else append...
Constraints and manual frame manipulation are directly in conflict. You have to choose one or the other. You should instead "promote" the constraint you wish to change by Ctrl-dragging it to your view controller as an #IBOutlet in Storyboard. Then, you can manipulate its constant:
class MyViewController: UIViewController {
#IBOutlet weak var myPropoLeftEdgeConstraint: NSLayoutConstraint!
#IBAction doChangePropo(sender: AnyObject) {
myPropoLeftEdgeConstraint.constant -= view.frame.width
view.layoutIfNeeded()
}
}
This is already covered in Objective C in many places, so just do a search on programmatically changing an NSLayoutConstraint in code if you can read those examples.
How to edit constraint in code
(Edit to make more applicable: generally constraints should be animated for a clean user experience. Otherwise the eye is confused.)
You can easily animate the constraint adjustment by wrapping view.layoutIfneeded in a UIView.animateWithDuration(duration) { ... } block.

Swift LayoutSubviews moving all subviews every user interaction

I apologize if this question has been already addressed, but I cannot find it.
I thought it would be simple enough to animate a UIImageView from offscreen onto the screen at certain points in my program. So I created the UIImageView and coded it up, but am getting a lot of strange behaviour. I have narrowed it down to the fact that layoutSubviews is getting called every user interaction (every button press) and it is resetting the size and location of all my items. I am using auto layout for every screen item save this one, so that is fine for the things I want auto layed out. But this one item is constantly being moved back to it's starting location. I proved it this way:
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad")
let screenWidth = UIScreen.mainScreen().bounds.width
let screenHeight = UIScreen.mainScreen().bounds.height
print(image.center)
image.center = CGPointMake(screenWidth / 2, image.bounds.height / -2)
print(image.center)
}
override func viewWillLayoutSubviews() {
print("viewWillLayoutSubviews")
print(image.center)
}
override func viewDidLayoutSubviews() {
print("viewDidLayoutSubviews")
print(image.center)
}
This is the result I get:
viewDidLoad
(294.0, 228.0)
(160.0, -64.0)
viewWillLayoutSubviews
(160.0, -64.0)
viewDidLayoutSubviews
(294.0, 228.0)
I don't have any constraints attached to this one view. Thoughts? I guess I could store the location and constantly move it around manually, but I'm sure there is a switch somewhere that turns off the autolayout for specific items. I just can't find it.
Thanks for your help...
The image must have autoresizingMasks that are getting translated into constraints.
Disable it by doing this:
image.translatesAutoresizingMaskIntoConstraints = false

How to setup a view with a half of screen height?

I want to set view1's height to half of the screen's height for all devices (when the device in the portrait mode)
Here is what I want it to look like:
so I make an auto layout of View1's height
#IBOutlet weak var heighConstraint: NSLayoutConstraint!
my viewwillappear function here:
override func viewWillAppear(animated: Bool) {
self. heighConstraint.constant = self.view.frame.size.height / 2
}
But it's not worked when I ran my app. what's wrong in here?
I know the accepted answer is correct but there is simpler method to do so -
Add the view (the one shown in yellow color). Pin it to three edges (top, leading and trailing). I have set it as 0 but change it as per your need.
Create Height Equal to constraint to main View as
Open that Constraint in the Inspector view and edit the multiplier as 0.5.
Setting it as 0.5 takes the height value of half the height of mainView.
Just make sure FirstItem = View1 and SecondItem = SuperView as shown in the image.
Try to change heightConstraint's constant value in viewDidLayoutSubviews method.
override func viewDidLayoutSubviews() {
heightConstraint.constant = self.view.frame.size.height / 2
}
Please try this out. Hope it will help you out. The below line will take the bounds of the device and will set the frame or height according to it.
view1.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height/2);
Hope this helps!!! Good Luck...

Resources