bounds of a UIView changes after viewDidLoad - ios

I have a view with a number of subviews. The subviews all have size constraints, built in the storyboard.
part of viewDidLoad() is to programmatically add a number of buttons. And I'm using the subview's bounds to known where to add the buttons to take up available screen real estate. As a simplified example:
override func viewDidLoad()
{
super.viewDidLoad()
let bottom = buttonView.bounds.maxY
let right = buttonView.bounds.maxX
let button = UIButton()
button.frame = CGRect(x: CGFloat(0.0),
y: CGFloat(0.0),
width: CGFloat(right),
height: CGFloat(bottom))
button.addTarget(self, action: #selector(buttonPushed(_:)), for: .touchUpInside)
buttonView.addSubview(button)
print("buttonview frame = \(buttonView.frame)")
}
override func viewWillAppear()
{
super.viewWillAppear()
print("buttonview frame = \(buttonView.frame)")
}
What I see happen in the simulator (and on hardware) is that the views are all sized according to how I had it designed in the storyboard, matching the hardware I had designed it on (iPhone 11). When I run it on an iPhone 8, my subviews all run off screen, and the first print statement indicates a width of 414.0. The constraints are applied sometime before viewWillAppear, and the second print statement indicates a width of 375.0. But my button isn't resized to fit. It still continues off screen.
How do I programmatically add my button subviews (this example only has the 1, code has 20 being built in a loop) to adhere to the constraints of the superview bounds, after I know what they actually are?

you have to add constraint by code, for example.
1) first I will create the button.
lazy var closeButton : UIButton = {
let button = UIButton(type: .custom)
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .blue
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
return button
}()
2) with this code I will add the button to the main view, and set the constraint.
self.view.addSubview(closeButton)
NSLayoutConstraint.activate([
closeButton.heightAnchor.constraint(equalToConstant: 20),
closeButton.widthAnchor.constraint(equalToConstant: 20),
closeButton.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20),
closeButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)]
but if you want to understand really how work this please the follow link
How to add constraints programmatically using Swift

Related

Constraints Issues On UI button

While practicing programmatic constraints using anchors ,I came across a problem that hides the visibility of the button when using an iPhone 8 or 8 plus simulator as shown in the image below. This is due to the current coordinate values I set for the button. However the button becomes visible when I switch to an iPhone 12. How do I set the co-ordinate values in a way that makes the button visible and in same positions on the iPhone 8 or 8 plus ?
let iosImageView: UIImageView = {
let imageview = UIImageView(image: #imageLiteral(resourceName: "icons8-ios-logo-128"))
imageview.translatesAutoresizingMaskIntoConstraints = false
return imageview
}()
let press: UIButton = {
let buttonPress = UIButton.init(type: .roundedRect)
buttonPress.setTitle("Tap Me", for: .normal)
buttonPress.backgroundColor = .black
buttonPress.frame = CGRect(x: 110, y: 700, width: 200, height: 50)
return buttonPress
}()
override func viewDidLoad() {
super.viewDidLoad()
addSubviews()
setConstraints()
// Do any additional setup after loading the view.
}
func addSubviews(){
view.addSubview(iosImageView)
view.addSubview(press)
}
func setConstraints(){
NSLayoutConstraint.activate([
iosImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
iosImageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 200),
iosImageView.widthAnchor.constraint(equalToConstant: 200),
iosImageView.heightAnchor.constraint(equalToConstant: 200),
press.centerXAnchor.constraint(equalTo: view.centerXAnchor),
press.leadingAnchor.constraint(equalTo: view.leadingAnchor),
press.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}
Your constraints for press are invalid. You failed to specify a vertical position. And you forgot to set translatesAutoresizingMaskIntoConstraints to be false. I’m surprised the button ever appears.
(Also cut the line about buttonPress.frame. Frame and constraints are opposites; use one or the other.)

Question about putting a fixed button in a static tableviewController in Swift

I made a scrollable screen with a static tableview.
But I want to create a UIButton that is independent of scrolling this table view.
I want to anchor it to the bottom of the view as shown below.
Is it possible to dock a button like that at the bottom of the screen in a scrollable static tableview?
You should create a footer view for tableView to do this.
Programmatically
let footerView = UIView()
footerView.backgroundColor = .red // your color
// You have to give height and width yourself
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
button.setTitle("<title>", for: .normal)
button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
footerView.addSubview(button)
via Interface Builder
Simply you should drag and drop UIView (CMD + Shift + L > type uiview) to your tableView and then add a button to your footerView, set constraints.
Then you should add this footerView to your tableView
tableView.tableFooterView = footerView
Create an action for your button
#objc func didTapButton(_ sender: UIButton) {
print("didTapButton called")
}

Getting the position of my UIBarButtonItem in iOS 11

On App Start, I highlight one of my BarButtonItems. Since iOS11 I am not able to do this anymore because I need to initialise it on another way.
First my old ios 10 code. I saved my barButtonItemView after initialising it.
let item1 = UIBarButtonItem(image: UIImage(named: "iconProfile"), style: .plain, target: self, action: #selector(pushSettings))
self.navigationItem.setRightBarButtonItems([item1], animated: true)
if let view = self.navigationItem.rightBarButtonItem?.value(forKey: "view") as? UIView {
barButtonItemView = view
}
Now I was able to access the position of barButtonItem just by using the frame
barButtonItemView.frame.topMiddle.x
With ios 11 the picture on my UIBarButtonItem gets smaller. I was reading that I have to resize them by using constraints. So now I initialise my UIBarButtons by using this function:
let imageView = UIImageView(image: UIImage(named: imageName))
imageView.frame = CGRect(x: 5, y: 7, width: 20, height: 20)
let button = UIButton()
button.frame = CGRect(x: 0, y: 0, width: 30, height: 34)
button.addTarget(self, action: action, for: .touchUpInside)
button.widthAnchor.constraint(equalToConstant: 30).isActive = true
button.heightAnchor.constraint(equalToConstant: 34).isActive = true
button.addSubview(imageView)
let barItem = UIBarButtonItem(customView: button)
return barItem
I set my rightBarButtonItem on the same way and try to get the view on the same way.
self.navigationItem.setRightBarButtonItems([item1], animated: true)
if let view = self.navigationItem.rightBarButtonItem?.value(forKey: "view") as? UIView {
barButtonItemView = view
}
But this time my barButtonItemView has the x and y values set to 0,0. Has anyone an idea how I can get the position of my BarButtonItem depending on my screen?
What I tried
The first solution I tried is to call layoutIfNeeded() before I try to get the frame again. This is not working as well as the x and y values are still 0,0.
First, if your UIBarButtonItem only needs to display an UIImage, you should use [UIBarButtonItem initWithImage:style:target:action:] instead of customView for more standard layout. And if you want to custom the size of UIBarButtonItem, you can resize the image.
Second, before iOS 10, UIBarButtonItem's view was added in the UINavigationBar directly, but after iOS 11, UIBarButtonItem was added in a UIStackView, and the stackView was added in the UINavigationBar, so if you get a (0, 0) from the customView's frame.origin, it means that the customView is layout at the (0, 0) origin in the stackView.
Third, the view of the UIBarButtonItem would not be initialized until the UINavigationBar was shown and your UIBarButtonItem was put in the bar, so you can not get the view when the UIBarButtonItem just be initialized. Maybe you can try to get the view and its frame in your viewController's viewWillAppear: or viewDidAppear:.

define UIButton programmatically swift

I'm trying to add a button programmatically as follows.
lazy var myButton: UIButton = {
let button = UIButton(type: .System)
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = UIColor.blueColor()
button.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height / 2)
button.addTarget(self, action: "buttonAction", forControlEvents: .TouchUpInside)
return button
}()
My intention was to create a button with view's width and height, half of view's height. And I also have LeftAnchor, RightAnchor, WidthAnchor, TopAnchor constraints to this button.
I have the following piece of code in my viewDidLoad()
view.addSubview(myButton)
when I try to run this code, I'm not able to see exactly what i want to have on my simulator.
I would like to see button width = view' width and height of button = view height /2
instead I see small button on the left top of the simulator. How do i resolve this issue?
Thanks !
A better bet would be to use AutoLayoutConstraints.
var myButtonHeight: NSLayoutConstraint
view.addSubview(myButton)
myButton.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
myButtonHeight = myButton.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5)
myButtonHeight.isActive = true
It's not clear from your comment if changing of the button height is onTouchDown, of if its a toggle as a result of onTouchUpInside, but either way
myButtonHeight.constant = (buttonShouldBeTall) ? 20 : 0
view.setNeedsLayout()
Please keep in mind you'll need to position the leading/trailing/centerX anchor and leading/trailing/centerY anchor as well, depending on where you need it to be

How to make auto resizing buttons via swift 3 that work between different Iphones

I'll post down below a part of my code on an app I'm working on for fun, the concept it's different, but the design of the camera session is very similar with the instagram app. I'm also using the PageMenu cocoa pod, that is really good and easy to implement via code.
override func viewDidLoad() {
super.viewDidLoad()
pageMenu?.delegate = self
photoControllerBG.frame = CGRect(x: 0, y : self.view.frame.minY, width: self.view.frame.width, height: self.view.frame.height )
let cameraButton = UIButton(frame: CGRect(x: self.view.frame.midX - , y: photoControllerBG.frame.minY + (self.view.frame.maxY/20*1), width: 130, height: 130))
cameraButton.addTarget(self, action: #selector(cameraButtonPressed(button:)), for: .touchUpInside)
cameraButton.setImage(#imageLiteral(resourceName: "Camera Button.png"), for: UIControlState.normal)
self.view.addSubview(cameraButton)
}
At the moment, the button on an iPhone 7 Plus will display like I want it to, centered in the ViewController and with the Image of the camera button with the same width and height so it stay a perfect circle. The problem presents itself when i switch the simulator with a iPhone SE or iPhone 6, where the button will become too big and not centered. Can you guys help me to find a math formula that it can be used to solve this big but small problem?
Your question implies doing the following in code (swift). Unless you are creating the button in swift I wouldn't do that at all. So, If you have a button created in a storyboard you can scale it appropriately as follows:-
I would use a proportional width constraint combined with an aspect ratio constraint in the story board to achieve this.
It may not be apparent straight away how to do this so I attach a picture journey.
Add your button to the view controller. Image shows final constraints.
Add an Equal Width constraint between the button and it's superview
The button doesn't have equal width to it's superview! My button is 100 px wide and the superview is 375 px wide. So let's calculate that ratio to help us calculate the proportional width.
Edit the Equal width constraint by using the proportional width above as the multiplier.
Add an aspect ratio to the button
Add any remaining constraints (In my case I centred the button horizontally and vertically)
Your constraints for the button should look like this:
let label = UILabel()
label.text = "title"
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setImage(#imageLiteral(resourceName: "image"), for: .normal)
view.addSubview(button)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 16)
])
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.topAnchor.constraint(equalTo: label.bottomAnchor),
button.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.3), //change your multiplier
button.heightAnchor.constraint(equalTo: button.widthAnchor)
])

Resources