define UIButton programmatically swift - ios

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

Related

bounds of a UIView changes after viewDidLoad

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

Why is a button with an image in it making the titleLable text cut off?

I have this code below which creates a button in code and centers the button in the middle of its superview:
let cameraButton: UIButton = {
let button = UIButton()
button.setImage(UIImage(named: "cam"), for: .normal)
button.setTitle("Take Pic", for: .normal)
button.setTitleColor(UIColor.black, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
return button
}()
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
view.addSubview(cameraButton)
cameraButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
cameraButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
Everything is working fine (as in the button is being centered in the center of the view) but the titleLabel text is being cut off for some reason (shown in the picture below):
I thought buttons have an intrinsic width and height so why would the titleLabel be cut off here? Shouldn't the width just expand based on the content inside of it (the imageView as well as the label)? Can someone advise me a way to fix this?
Try with setting below attributes
cameraButton.titleLabel!.numberOfLines = 0
cameraButton.titleLabel!.adjustsFontSizeToFitWidth = true
cameraButton.titleLabel!.lineBreakMode = NSLineBreakMode.byWordWrapping

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)
])

(Swift) programmatically constrain UIButton to corner

I have the following code for an image that is a round button:
let settingsButton = UIButton(type: .Custom)
settingsButton.frame = CGRectMake(160, 100, 50, 50)
settingsButton.layer.cornerRadius = 0.5 * settingsButton.bounds.size.width
settingsButton.setImage(UIImage(named:"settingsButton.png"), forState: .Normal)
settingsButton.clipsToBounds = true
view.addSubview(settingsButton)
I want to constrain it to the top left corner of my view controller, but since I made this button programmatically, I can't see it in my storyboard and therefore cannot move and constrain it manually. Is there a way to be able to see this programmatically created button in my storyboard's view controller? If not, how can I programmatically constrain this button I created to the top left corner of my view controller?
Any help is greatly appreciated!
The easiest way to do this, since you're creating the button in code, is to use the button's autoresizing mask. First, set the button's frame so it's in the top right corner of the superview. Then set the button's autoresizingMask to allow only the distances to the left and bottom edges of the superview to vary:
settingsButton.frame = CGRect(x: view.bounds.maxX - 50, y: 0, width: 50, height: 50)
settingsButton.autoresizingMask = [.flexibleLeftMargin, .flexibleBottomMargin]
view.addSubview(settingsButton)
My code is in Swift 3 syntax but it should be trivial to convert it so Swift 2.
Keep in mind that autoresizing masks work fine under auto layout. Many of Apple's standard classes still use autoresizing masks internally. Xcode 8 added the ability to mix constraints and autoresizing masks in a storyboard or xib, so clearly Apple thinks you should use autoresizing when it's a good fit.
If I interpret constrain as-in using constraints, you can use layout anchors. The gotchas here are:
Always set translatesAutoresizingMaskIntoConstraints = false on your view.
Set .active = true on your layout anchors.
Only available in iOS >= 9.0 (use normal NSlayoutConstraints if you need to support earlier versions of iOS).
Example code:
let settingsButton = UIButton(type: .Custom)
view.addSubview(settingsButton)
settingsButton.backgroundColor = UIColor.redColor()
settingsButton.translatesAutoresizingMaskIntoConstraints = false
settingsButton.widthAnchor.constraintEqualToConstant(50).active = true
settingsButton.heightAnchor.constraintEqualToConstant(50).active = true
settingsButton.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 10).active = true
settingsButton.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor, constant: -10).active = true
settingsButton.setNeedsLayout()
settingsButton.layoutIfNeeded()
settingsButton.layer.cornerRadius = 0.5 * settingsButton.bounds.size.width
settingsButton.setImage(UIImage(named:"settingsButton.png"), forState: .Normal)
settingsButton.clipsToBounds = true
Note that using constraints is superior to setting frames because constraints adapt to changes in the parent view sizeĀ (e.g device rotation to landscape mode).
You can use this :
let settingsButton = UIButton()
settingsButton.translatesAutoresizingMaskIntoConstraints = false
settingsButton.trailingAnchor.constraint(equalTo: view.leadingAnchor,constant: 160).isActive = true
settingsButton.bottomAnchor.constraint(equalTo: view.topAnchor,constant: 100).isActive = true
settingsButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
settingsButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
settingsButton.widthAnchor.constraint(equalToConstant: 50).isActive = true
settingsButton.layer.cornerRadius = 0.5 * settingsButton.bounds.size.width
settingsButton.clipsToBounds = true
view.addSubview(settingsButton)

Add Button to UIView Created Programmatically

I created UIView and Button programmatically
var width = self.view.frame.width - 8
var height = width/8
newView.frame = CGRectMake(4, 39, width, height)
newView.backgroundColor = UIColor.greenColor()
self.view.addSubview(newView)
var button = UIButton.buttonWithType(UIButtonType.System) as! UIButton
button.frame = newView.frame
button.backgroundColor = UIColor.whiteColor()
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
button.setTitle(" All Hospitals/Clinics", forState: UIControlState.Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
newView.addSubview(button)
I want the button to be inside the UIView, and to have exactly the same location, width and height of UIView
but the result is this
What is wrong with my code ?
Thanks in advance
The issue is caused by this line of code:
button.frame = newView.frame // Equivalent to button.frame = CGRectMake(4, 39, width, height)
In your current implementation the x position of button is 4 and y position is 39, that's why you are getting the result like that way. You need to specify the button frame relative to the newView.
Change the button frame setting code to:
button.frame = CGRectMake(0, 0, width, height)
You should use bounds instead of the frame of the view.
button.frame = newView.bounds
Bounds returns the CGRect of the view coordinates in its own coordinate space, while frame returns the same but in it's parent's coordinate space.
So newView.bounds would return a CGRect like (0,0,width_of_newView,height_of_newview)
your button frame is wrong.
when you declared x and y property of a frame, it is related to its superview.
since you declare your button frame as (4, 39, width, height) it will be placed on coordinate x = 4, y = 39 in view's frame which is exactly like your picture.
if you want to make it like your view, change x and y to 0.
you can use Anchor
lazy var testButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
button.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
button.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
button.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
return button
}()
override func viewDidLoad() {
self.view.addSubview(testButton)
}

Resources