Title not showing for custom UIButton class - ios

I have created a custom UIButton class which features a round frame. The problem is although I set up the title property of each button from the storyboard they are not showing. I end up with round buttons with no titles showing inside them. I am trying to do a keypad like the one in default iOS passcode screen. My main view background color is not white and I am not using any background images for the buttons. Here is my code for the custom UIButton class.
import Foundation
import UIKit
class MyOwnButton: UIButton {
override init(frame: CGRect){
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
self.clipsToBounds = true
self.titleLabel?.font = UIFont.systemFontOfSize(33.0)
self.titleLabel?.textColor = UIColor.whiteColor()
self.layer.cornerRadius = self.frame.size.width / 2.0
self.layer.borderColor = UIColor.whiteColor().CGColor
self.layer.borderWidth = 2.0
}
}

Had same issue, this answer worked for me: Custom UIButton subclass not displaying title
Add super.layoutSubviews() after you override the function.

Have you set your UIButton's class as your custom class in storyboard??

Try to put all the things in init method and check.
import Foundation
import UIKit
class MyOwnButton: UIButton {
override init(frame: CGRect){
super.init(frame: frame)
self.clipsToBounds = true
self.titleLabel?.font = UIFont.systemFontOfSize(33.0)
self.titleLabel?.textColor = UIColor.whiteColor()
self.layer.cornerRadius = self.frame.size.width / 2.0
self.layer.borderColor = UIColor.whiteColor().CGColor
self.layer.borderWidth = 2.0
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}

Here is working code for Swift 4
import UIKit
class MyOwnButton: UIButton {
override init(frame: CGRect){
super.init(frame: frame)
commonSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonSetup()
}
private func commonSetup() {
self.clipsToBounds = true
self.titleLabel?.font = UIFont.systemFont(ofSize: 33.0)
self.titleLabel?.textColor = UIColor.white
self.layer.cornerRadius = self.frame.size.width / 2.0
self.layer.borderColor = UIColor.white.cgColor
self.layer.borderWidth = 2.0
}
}

After setting the title of the button, simply:
[button sizeToFit];

Related

How do you call an IBOutlet element's initializer?

I wrote the following subclass of UITextField:
var imageView: UIButton? = nil
var options: [String]? = nil
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 30)
override init(frame: CGRect) {
super.init(frame:frame)
self.backgroundColor = Constants.darkPurple
self.textColor = .white
self.layer.cornerRadius = 10
self.clipsToBounds = true
self.translatesAutoresizingMaskIntoConstraints = false
self.tintColor = .clear
Constants.styleDropDownField(self)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//fatalError("init(coder:) has not been implemented")
}
}
When I add instances of this class programmatically, it works fine. But when I add an instance of the class in the storyboard and then connect it with an IBAction, it's just a blank white text field without any of the properties I assigned in the class's initializer - it seems that the initializer isn't being called at all. Is there any way to call the element's initializer? Or is there another function, similar to viewDidLoad, that will run when the text field is loaded?
You'll have to call the implementation given in init(frame:) in init(coder:) because this method is called when used from the storyboard. Here is the code:
override init(frame: CGRect) {
super.init(frame:frame)
initialSetup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialSetup()
}
func initialSetup() {
self.backgroundColor = Constants.darkPurple
self.textColor = .white
self.layer.cornerRadius = 10
self.clipsToBounds = true
self.translatesAutoresizingMaskIntoConstraints = false
self.tintColor = .clear
Constants.styleDropDownField(self)
}
You can't call the initialiser of the component added in storyboard. But you are going in right direction. Create a common method to set these properties.
func commonSetup() {
self.backgroundColor = Constants.darkPurple
self.textColor = .white
self.layer.cornerRadius = 10
self.clipsToBounds = true
self.translatesAutoresizingMaskIntoConstraints = false
self.tintColor = .clear
Constants.styleDropDownField(self)
}
And call this method from three different methods
override func awakeFromNib() {
super.awakeFromNib()
self.commonSetup()
}
override init(frame: CGRect) {
super.init(frame:frame)
self.commonSetup()
}
//This method will be called when component is initialised from storyboard.
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonSetup()
}

Custom UIButton class does not show title

I have created a custom UIButton class. But the title does not show up. I only get the background color and the rounded corners. But the title is not visible.
Also when I run it in simulator, iOS 13+, its showing the title white. But when I run in my device i.e. iOS 12.4, its not working.
Here is my code:
public class CornerButton : UIButton {
public override init(frame: CGRect) {
super.init(frame: frame)
setup()
self.layoutIfNeeded()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
self.layoutIfNeeded()
}
func setup() {
self.titleLabel?.font = UIFont(name: "Poppins-SemiBold", size: 12)
self.backgroundColor = UIColor(named: "BarColor")
self.setTitleColor(.white, for: .normal) // this line is not working
self.clipsToBounds = true
}
public override func layoutSubviews() {
self.roundCorners(corners: [.topRight,.bottomLeft], radius: 10)
}
}
You need to call super.layoutSubviews()
public override func layoutSubviews() {
super.layoutSubviews()
self.roundCorners(corners: [.topRight,.bottomLeft], radius: 10)
}
BTW here you don't need layoutSubviews as you use it when you need to make something that depends on the actual measured bounds of the view and as you set a static radius you can omit it

Xcode #IBDesignable Button Background Color Not Rendering In Storyboard

Trying to show the button background color in the storyboard, the following code renders the border width and radius correctly but background doesn't show. In the simulator, the button's background color is rendered correctly.
import UIKit
let colorSunset = #colorLiteral(red: 0.9693382382, green: 0.5568749309, blue: 0, alpha: 1)
#IBDesignable class PrimaryButtonA: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
buttonA()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
buttonA()
}
func buttonA() {
self.layer.cornerRadius = 10
self.layer.borderWidth = 5
self.layer.backgroundColor = colorSunset.cgColor
}
}
Code Screenshot
Storyboard Screenshot
Simulator Screenshot
Xcode doesn't show any errors but there is a warning which is unrelated and is about the button's fixed width and height and the text will be clipped.
Thanks in advance for the help.
This is the solution that worked for me.
import UIKit
let colorSunset = #colorLiteral(red: 0.9693382382, green: 0.5568749309, blue: 0, alpha: 1)
#IBDesignable class PrimaryButtonA: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
buttonA()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
buttonA()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
backgroundColor = colorSunset
}
func buttonA() {
self.layer.cornerRadius = 10
self.layer.borderWidth = 5
// self.layer.backgroundColor = colorSunset.cgColor
}
}
There is no solution to this. This problem occurs because some times storyboard does not recognize IBDesignables. When you restart your XCode sometimes it gets recognized and sometimes it doesn't.

Rounded UIButton - iPad size

I have custom UIButton to have rounded edges
import UIKit
class RoundedButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = self.bounds.width * 0.5
self.backgroundColor = UIColor(patternImage: UIImage(named: "map.png")!)
self.setTitleColor(UIColor.white, for: UIControlState.normal)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.layer.cornerRadius = self.bounds.width * 0.5
self.backgroundColor = UIColor(patternImage: UIImage(named: "map.png")!)
self.setTitleColor(UIColor.white, for: UIControlState.normal)
}
}
Now I am using this "RoundedButton" (size of 110, 110) in a UIViewcontroller's XIB file and the constraints are set to maintain the aspect ratio w.r.t UIViewcontrollers view.
The button looks rounded in iPhone simulators but the button is NOT rounded in iPad simulator. When I set the layer.cornerRadius property in viewDidAppear then the button is rounded in iPad simulator.
Please see images
I am looking for an alternative solution than re-defining layer corner radius again in viewDidappear.
Thanks
override method layoutSubviews like this:
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.width * 0.5
}
Also you can now remove cornerRadius line from init
For more go to documentation of UIView: https://developer.apple.com/documentation/uikit/uiview/1622482-layoutsubviews
Override layoutSubviews function:
import UIKit
class RoundedButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor(patternImage: UIImage(named: "map.png")!)
self.setTitleColor(UIColor.white, for: UIControlState.normal)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.backgroundColor = UIColor(patternImage: UIImage(named: "map.png")!)
self.setTitleColor(UIColor.white, for: UIControlState.normal)
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.width * 0.5
}
}
import UIKit
class RoundedButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
self.setTitleColor(UIColor.white, for: UIControlState.normal)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setTitleColor(UIColor.white, for: UIControlState.normal)
}
override func layoutSubviews() {
super.layoutSubviews()
self.layer.cornerRadius = self.bounds.width / 2
}
}
I have also create a code sample for you. RoundedButton

Instantiate custom button from code and Storyboard - how to make an init method

I would like to create a button like this:
import UIKit
class EKLikeButton: UIButton {
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.layer.cornerRadius = 5.0;
self.layer.borderColor = UIColor.redColor().CGColor
self.layer.borderWidth = 1.5
self.backgroundColor = UIColor.blueColor()
self.tintColor = UIColor.whiteColor()
}
}
but the only way to make it seems to be to set a pre-existing button in a Storyboard. I'd like to be able to do:
let btn = EKLikeButton()
btn.frame=CGRectMake(10.0, 10.0, 40.0, 40.0)
but when I try the above, I get
Missing argument for parameter 'coder' in call
How would I make an init function that can handle both from code or from storyboard in Swift?
This is what I usually do
class EKLikeButton: UIButton {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUp()
}
init(){
super.init(frame: CGRectZero)
setUp()
}
override init(frame: CGRect) {
super.init(frame: frame)
setUp()
}
func setUp(){
self.layer.cornerRadius = 5.0;
self.layer.borderColor = UIColor.redColor().CGColor
self.layer.borderWidth = 1.5
self.backgroundColor = UIColor.blueColor()
self.tintColor = UIColor.whiteColor()
}
}
That error message is telling you that it's looking for that coder param, because you only have that one init function. You haven't declared an initializer with no parameters, so you can't init like: EKLikeButton()
To add an init that accepts a frame parameter, you need to also implement:
override init(frame: CGRect) {
super.init(frame: frame)
// set up your frame, init, whatever
}
Then you can instantiate it like this:
let btn = EKLikeButton(CGRect(10, 10, 40, 40))

Resources