Swift UIButton With Icon and Text (not using edgeinsets) - ios

I'm trying to get a button with an icon to the left of some text:
Having trouble with my understanding of UIButton. Adding a title to the button works fine:
import UIKit
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 300, height: 25))
button.backgroundColor = .green
button.contentHorizontalAlignment = .left
button.contentVerticalAlignment = .fill
button.titleLabel!.backgroundColor = .blue
button.setTitle("639", for: .normal)
button.setTitleColor(.white, for: .normal)
but then when you add an image
button.setImage(UIImage(named: "test"), for: .normal)
button.imageView!.backgroundColor = .clear
button.imageView!.contentMode = .scaleAspectFit
it keeps it's original size (300px) and pushes the title out the right side out of the buttons bounds. (can't see it in screenshot as its only showing button frame)
What am I doing wrong? Why does the image retain it's original width even though its been scaled down? What does contentHorizontalAlignment even do if it allows items to be pushed out of frame?
I'm aware that you can set insets but this is being used in a re-useable view so I can't hardcode values.
Thanks for the help

I just made a button just like what you said.
By the way why don't you use inset.Apple has given us the opportunity to use this.Then why shouldn't we use this?
Note: You have to make trial and error to position the image and text correctly.
Autolayout:
And inset:
If it's not accurate i said you have to make trial and error. happy coding. :)

Related

How to set width and heigh of UIButton that is added as custom view of UIBarButtonItem when using SVG images?

I am having a vector image, downloaded from phosphor-icons:
I have downloaded .svg version of an icon.
When you open this vector file in image editor, you see that it has 192x192 dimensions.
Which I guess its not relevant at all when it comes to vectors files, but...
I have this code:
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
button.imageView?.contentMode = .scaleAspectFit
button.backgroundColor = .yellow
button.setImage(UIImage(named: "alien"), for: .normal)
button.setTitle(nil, for: .normal)
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
let item = UIBarButtonItem(customView: button)
navigationItem.setRightBarButtonItems([item], animated: true)
Now the thing is, if I use this original svg image(192x192), a button shrinks and it looks like this:
but I don't want this button to have these dimensions, but rather those that are set with:
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
Now, if I go to an image editor, and change the size of this vector file to 22x22 (it still stays svg file), it shows up like this:
which looks how I want.
The thing is, I thought that Xcode will generate required png file from this svg based on device's pixel density. So in this case, say, on newer devices that use #3x images, at compile time, cause my button is defined as 32x32 points, a 96px X 96px image will be created and used as #3x image.
Also, I thought that this is going to work like described, no matter what "dimensions" a physical .svg file is, cause it's a vector, and it should be up/down scaled as view dictates. Where I am wrong with this, and how to make this button to look the same as from second image, no matter of what are actual .svg dimensions?
EDIT:
In Attributes Inspector, for this asset, I have set Preserve Vector Data and selected Single Scale option.
Another way of to achieve this without using autolayout constraints , like you commented , is using a UIView() for customview
let view = UIView(frame: button.frame)
view.addSubview(button)
let item = UIBarButtonItem(customView: view)
self.navigationItem.setRightBarButtonItems([item], animated: true)
When adding a button as the customView for a bar button item, UIKit will automatically use auto-layout.
So, your init of UIButton(frame: CGRect(x: 0, y: 0, width: 32, height: 32)) doesn't have any effect.
I grabbed that "alien.svg" from the site you linked to and used it un-edited, with these settings:
Then, using this code (in viewDidLoad()):
let button = UIButton()
button.backgroundColor = .yellow
button.setImage(UIImage(named: "alien"), for: .normal)
button.setTitle(nil, for: .normal)
// adding the button as a custom bar button item view
// automatically uses auto-layout
button.widthAnchor.constraint(equalToConstant: 32).isActive = true
button.heightAnchor.constraint(equalTo: button.widthAnchor).isActive = true
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
let item = UIBarButtonItem(customView: button)
// you can use either
//navigationItem.rightBarButtonItem = item
// or
navigationItem.setRightBarButtonItems([item], animated: true)
We get this result:

UIBarButtonItem with custom UIButton is invisible on iOS <= 10

I need to create a "burger menu" button for my app on my navigationController's left side but since the NavCon is transparent I need to have a shadow on my icon.
Thus I've created a custom UIButton with an image, a drop shadow and the added it as a custom view on a UIBarButtonItem as follows:
let menuButton = UIButton(type: .custom)
menuButton.addTarget(self, action: #selector(showSideMenu), for: .touchUpInside)
menuButton.setImage(#imageLiteral(resourceName: "menu_white"), for: .normal)
menuButton.tintColor = UIColor.white
menuButton.layer.masksToBounds = false
menuButton.layer.shadowColor = UIColor.black.cgColor
menuButton.layer.shadowOpacity = 1.0
menuButton.layer.shadowRadius = 5
menuButton.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: menuButton)
The code above works perfectly fine on iOS 11, but when I tested my app on ios 9 and 10 (both simulators and real devices) the menu icon is invisible. It is clickable and works as expected, but there is no visible icon.
In the View Hierarchy Debugger I can see a UIButton with 0 width and height, while in ios 11 I can see the normal UIButtonBarStackview with the embedded UIButton.
Any ideas on how to fix this and why this is happening? Thank you very much!
Please mention the button frame
let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 70, height: 40))
It may helps to you thank you
You can just call menuButton.sizeToFit() and it will work.

How to change the height and width of a button in iOS app using Swift 4.0 which is developed using Swift 3.0

I am completely new to iOS development and I am supposed to fix some bugs in an iOS app which is made using Swift 3.0 and Xcode 8 and it works almost fine. But when I open it with Xcode 9 and Swift 4.0 it shows some buttons way different that they were before.
Here is the source code for one of those buttons.
let button: UIButton = UIButton.init(type: UIButtonType.custom)
//set image for button
button.setImage(UIImage(named: "menu.png"), for: UIControlState())
button.frame = CGRect(x: 0, y: 0, width: 30, height: 23)
let barButton = UIBarButtonItem(customView: button)
button.addTarget(self, action: #selector(ViewController.shareButtonPressed), for: UIControlEvents.touchUpInside)
self.navigationItem.leftBarButtonItem = barButton
this code is inside the ViewDidLoad method. My problem is when I remove,
button.setImage(UIImage(named: "menu.png"), for: UIControlState())
it disappears the button but when I change the height and the width from,
button.frame = CGRect(x: 0, y: 0, width: 30, height: 23)
it changes nothing.
My problem is how can I fix this bug. Any suggestion, answer is highly appreciated and if the given details are not enough, please mention. Thank you!
Beginning with iOS 11, views added to toolbars using UIBarButtonItem using UIBarButtonItem(customView:) are now laid out using auto layout. You should add sizing constraints on your button. For example:
button.widthAnchor.constraintEqualToConstant(30.0).isActive = true
button.heightAnchor.constraintEqualToConstant(23.0).isActive = true
Otherwise, auto layout will use the intrinsic content size of your header view which is likely not what you expect.
For more information see the WWDC 2017 session Updating your app for iOS 11.
swift 4:
button.widthAnchor.constraint(equalToConstant: 30.0).isActive = true
button.heightAnchor.constraint(equalToConstant: 20.0).isActive = true
You can customize width and height of button using storyboard in Xcode. Just select your button and open this window.
After that just add the height constraints.

Custom bar button item not sizing properly

I have a custom app that includes a custom bar button item, with Swift 3 it was sized appropriately but after updating to Swift 4 it is no longer sizing to the constraints provided. This is my code:
let infoButton = UIButton.init(type: .custom)
infoButton.setImage(UIImage(named: "info button white.png"), for: UIControlState.normal)
infoButton.addTarget(self, action: #selector(StartViewController.infoButtonPressed), for: UIControlEvents.touchUpInside)
infoButton.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
let barButton = UIBarButtonItem(customView: infoButton)
self.navigationItem.rightBarButtonItem = barButton
I tried changing the CGRect numbers to see if there would be any change, and there is not, it is sizing to the limits of the navigation bar, and frankly now looks quite ugly.
Any ideas about what changed in Swift 4? I am running Xcode 9.0(9A235)
Try setting constraints like this:
infoButton.widthAnchor.constraint(equalToConstant: 25).isActive = true
infoButton.heightAnchor.constraint(equalToConstant: 25).isActive = true
Or use images of the correct size.

Display Image and Title Simultaneously on UIButton - Swift 3

How can I display a title and image simultaneously on a UIbutton? I tried to follow Display image and text in Button which uses swift 2 but the same process only displays the image in swift 3, with the title hidden. The image source file is 35x35 pixels. My code:
let folderButton = UIButton(frame: CGRect(x: 100 , y: 200, width: 200, height: 41))
folderButton.layer.borderColor = UIColor.black.cgColor
folderButton.layer.borderWidth = 1
folderButton.imageEdgeInsets = UIEdgeInsets(top: 0,left: 162,bottom: 3,right: 3)
folderButton.titleEdgeInsets = UIEdgeInsets(top: 0,left: 0,bottom: 0,right: 41)
folderButton.setImage(UIImage(named:"FolderIcon35"), for: UIControlState.normal)
folderButton.setTitle("Test", for: UIControlState.selected)
folderButton.setTitleColor(.black, for: .normal)
view.addSubview(folderButton)
current Output
Need a programatic solution as I am not using storyboard. Thanks!
I think you should set the title for UIControlState.normal
folderButton.setTitle("Test", for:.normal)
Try this: folderButton.setTitle("yourTitle", for: UIControlState. normal)
The problem is you are setting your title for UIButton selected mode only. SO when you select the button the title should display with your current code. For showing title in normal mode you should change the title set state to .normal.
folderButton.setTitle("Test", for: UIControlState.normal)
For UIButton in iOS, we can change the appearance of button depending upon the state, namely Normal and Selected.
Here, you are setting the title of button when button is pressed so you need to add additional line to your code by setting the state to normal.
folderButton.setTitle("Test", for: UIControlState.selected)
folderButton.setTitle("Test", for: UIControlState.normal)
For more reference on UIButton in ios, Visit: UIButton

Resources