Round UIBarButtonItems in Swift - ios

I am trying to make round (sort of notification counter which you see on most of the apps) UIBarButtonItem in Swift. I know how to do it but the thing is it is actually being round only when I am setting the width as 34 and height as 24. Are these magic numbers for UIBarButtonItems ? If I set the width or height (same , my desired frame is 30 x 30) for something else and calculate the cornerRadius based on the width then it is not perfect circle rather rounded rectangle. What is I am doing wrong ? My code is below :
let button = UIButton(type: .custom)
button.frame = CGRect(x: 0, y: 0, width: 34, height: 24)
button.backgroundColor = DarkModeUtil.isDarkMode() ? UIColor.white : UIColor.black
button.setTitle("\(self.pickedAppActions.count > 9 ? "9+" : "\(self.pickedAppActions.count)")", for: .normal)
button.setTitleColor(DarkModeUtil.isDarkMode() ? .black : UIColor.white, for: .normal)
button.contentHorizontalAlignment = .center
button.titleLabel?.fitSize()
button.layer.cornerRadius = button.bounds.size.width / 2
button.clipsToBounds = true
button.addTarget(self, action: #selector(counterTapped(_:)), for: [.touchUpInside])
let doneItem = UIBarButtonItem(image: UIImage(named: "done")?.withRenderingMode(.alwaysTemplate), style: .plain, target: self, action: #selector(doneButtonClicked(_:)))
doneItem.tintColor = DarkModeUtil.isDarkMode() ? .white : .black
let counterButton = UIBarButtonItem(customView: button)
let buttons:[UIBarButtonItem] = [doneItem,counterButton]
self.navigationItem.rightBarButtonItems = buttons
If I set same width and height for example 30 x 30 I get button like this:

make height and width 34 work for me. here is a code. also no need to change button.frame.size.width / 2.
let button = UIButton(type: .custom)
button.frame = CGRect(x: 0, y: 0, width: 34, height: 34)
button.backgroundColor = DarkModeUtil.isDarkMode() ? UIColor.white : UIColor.black
button.setTitle("\(self.pickedAppActions.count > 9 ? "9+" : "\(self.pickedAppActions.count)")", for: .normal)
button.setTitleColor(DarkModeUtil.isDarkMode() ? .black : UIColor.white, for: .normal)
button.contentHorizontalAlignment = .center
button.titleLabel?.fitSize()
button.layer.cornerRadius = button.bounds.size.width / 2
button.clipsToBounds = true
button.addTarget(self, action: #selector(counterTapped(_:)), for: [.touchUpInside])
let doneItem = UIBarButtonItem(image: UIImage(named: "done")?.withRenderingMode(.alwaysTemplate), style: .plain, target: self, action: #selector(doneButtonClicked(_:)))
doneItem.tintColor = DarkModeUtil.isDarkMode() ? .white : .black
let counterButton = UIBarButtonItem(customView: button)
let buttons:[UIBarButtonItem] = [doneItem,counterButton]
self.navigationItem.rightBarButtonItems = buttons

You can set corner radius of the Button using
button.frame = CGRect(x: 0, y: 0, width: 84, height: 40)
button.layer.cornerRadius = button.bounds.size.height / 2
Note: Button Maximum height: 44 and Minimum height: 34 in UINavigationBar as checked from view hierarchy.

Please try with this code :
For Round button you need to make height and width same value :
let button = UIButton(type: .custom)
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
button.backgroundColor = UIColor.black
button.setTitle("999", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 12.0)
button.titleLabel?.minimumScaleFactor = 0.5
button.titleLabel?.numberOfLines = 0
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.layer.cornerRadius = button.frame.size.height/2
button.clipsToBounds = true
let counterButton = UIBarButtonItem(customView: button)
let buttons:[UIBarButtonItem] = [counterButton]
self.navigationItem.rightBarButtonItems = buttons

Related

Trying to make a UIButton a circle

Im currently trying to make a button into a circle shape and here is my code:
var raffleButton:UIButton = {
var button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.titleLabel?.font = UIFont(name: "AvenirNext-Bold", size: 19)
button.setTitle("Tap To Enter Raffle!", for: .normal)
button.setTitleColor(UIColor.red, for: .normal)
button.backgroundColor = .white
button.layer.masksToBounds = true
button.frame = CGRect(x: 1600, y: 160, width: 160, height: 160)
button.layer.cornerRadius = button.frame.width/2
return button
}()
However when I run the code the button is disfigured and looks like the following... round and football like.
Is there any reason why the button looks like it does instead of being a circle?
You have some confusion as to whether you are using autolayout or not.
You have set translatesAutoresizingMaskIntoConstraints to false, but then you are trying to manipulate the frame.
If you add constraints to set the width & height, you will get a result closer to what you are after, but you will still need to adjust your label or font to get it to fit:
var raffleButton:UIButton = {
var button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.titleLabel?.font = UIFont(name: "AvenirNext-Bold", size: 19)
button.setTitle("Tap To Enter Raffle!!", for: .normal)
button.setTitleColor(UIColor.red, for: .normal)
button.backgroundColor = .white
button.layer.masksToBounds = true
button.heightAnchor.constraint(equalToConstant: 160).isActive = true
button.widthAnchor.constraint(equalToConstant: 160).isActive = true
button.layer.cornerRadius = 80
return button
}()
Since you set button.translatesAutoresizingMaskIntoConstraints = false, this code won't work button.frame = CGRect(x: 1600, y: 160, width: 160, height: 160). The button's size will be changed during the layout process(won't be (160, 160) anymore). Therefore, it's not a circle.
you can either change button.translatesAutoresizingMaskIntoConstraints = false or try setting button's cornerRadius in viewDidLayoutSubviews method.
your button Height same as button width and then set this code..
anyButton.backgroundColor = .clear
anyButton.layer.cornerRadius = anyButton.frame.height / 2
anyButton.layer.borderWidth = 1
anyButton.layer.borderColor = UIColor.black.cgColor
One semi-obvious thing to note, is if the button frame's height and width is not equal, it will not be a circle :).

Set image and title both on RightBarButton

I want to set image and title both on rightBarButton. Title will come first. I searched a lot but all the articles are related to leftBarButton. So can anyone please tell me, how to set both of them?
func methodForSettingButtonClicked() {
let buttonSetting = UIButton(type: .custom)
buttonSetting.frame = CGRect(x: 0, y: 5, width: 25, height: 25)
let imageReg = UIImage(named: "setting")
buttonSetting.setTitle("Settings", for: .normal)
buttonSetting.setImage(imageReg, for: .normal)
let leftBarButton = UIBarButtonItem()
leftBarButton.customView = buttonSetting
self.navigationItem.rightBarButtonItem = leftBarButton;
}
try barbutton item with custom VIew as follows:-
let button = UIButton(type: .Custom)
button.setImage(UIImage(named: "icon_right"), forState: .Normal)
button.addTarget(self, action: "buttonAction", forControlEvents: .TouchUpInside)
button.frame = CGRectMake(0, 0, 53, 31)
button.imageEdgeInsets = UIEdgeInsetsMake(-1, 32, 1, -32)//move image to the right
let label = UILabel(frame: CGRectMake(3, 5, 50, 20))
label.font = UIFont(name: "Arial-BoldMT", size: 16)
label.text = "title"
label.textAlignment = .Center
label.textColor = UIColor.whiteColor()
label.backgroundColor = UIColor.clearColor()
button.addSubview(label)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = barButton
imageEdgeInsets plays a important role.
Try it as below and set title as you want
let button = UIButton(type: .system)
button.setImage(UIImage(named: "icon_image_name"), for: .normal)
button.setTitle("Categories", for: .normal)
button.addTarget(self, action: #selector(clickOnButtonActionMethod), for: .touchUpInside)
button.sizeToFit()
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
If you want then change button property as you want.
You can do like this way,
let button = UIButton(type: .custom)
button.setTitle("Settings", for: .normal)
button.setImage(#imageLiteral(resourceName: "settings"), for: .normal)
button.semanticContentAttribute = .forceRightToLeft
button.setTitleColor(UIColor.white, for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
It works for me, hope it can help you.

imageView in iOS 11 using Swift

I created 2 customs buttons in my navigation Controller. I have one left button and one right, and both have some text + an arrow icon. Since I updated to iOS 11, the size of icons has changed and I don't know why.
This this the difference between iOS 10 (Left) and iOS 11 (right):
How can I change that?
This is a piece of my code:
func addRightButton(){
rightButton = UIButton.init(type: .custom)
rightButton.setImage(UIImage(named: "back"), for: .normal)
rightButton.imageView?.contentMode = .scaleAspectFit
let width = UIScreen.main.bounds.size.width
if width < 375 {
rightButton.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: UIFont.Weight.bold)
rightButton.frame = CGRect.init(x: 0, y: 0, width: 75, height: 10)
} else {
rightButton.titleLabel?.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.bold)
rightButton.frame = CGRect.init(x: 0, y: 0, width: 100, height: 10)
}
rightButton.imageView!.transform = rightButton.imageView!.transform.rotated(by: CGFloat((Double.pi / 2) * -1))
rightButton.setTitle(" Mixte",for: .normal)
rightButton.addTarget(self, action: #selector(self.switchSex(_:)), for: UIControlEvents.touchUpInside)
let barButton = UIBarButtonItem(customView: rightButton)
self.navigationItem.rightBarButtonItem = barButton
}
You need to add width constraint for your button in xCode 9. Like this:
let width = yourButton.widthAnchor.constraint(equalToConstant: 75)
let height = yourButton.heightAnchor.constraint(equalToConstant: 10)
heightConstraint.isActive = true
widthConstraint.isActive = true

How to add multiple subviews on view without hiding the last added subview?

This is my code
var button = [UIButton?](count:3, repeatedValue: UIButton())
for i in 0...2{
button[i]!.tag = i
button[i]!.frame = CGRectMake(CGFloat(i) *(collectionViewLove?.frame.width)!/3,0,(collectionViewLove?.frame.width)!/3, 30)
button[i]!.setTitle(titleForButtonsOneSelected[i], forState: .Normal)
button[i]!.titleLabel?.adjustsFontSizeToFitWidth = true
button[i]!.layer.borderWidth = 1.0
button[i]!.layer.borderColor = UIColor.blueColor().CGColor
button[i]!.backgroundColor = UIColor.clearColor()
button[i]!.setTitleColor(UIColor.blackColor(), forState: .Normal)
view.addSubview(button[i]!)
}
The problem is only the last button added to the view is getting shown. How do I show all the button objects in the view?
EDIT:
The frame values for UIButton I am getting
(0.0, 0.0, 106.666666666667, 30.0)
(106.666666666667, 0.0, 106.666666666667, 30.0)
(213.333333333333, 0.0, 106.666666666667, 30.0)
let buttons = Array(0...2).map { number -> UIButton in
let button = UIButton(frame: CGRectMake(CGFloat(number) * collectionViewLove!.frame.width / 3, 0, collectionViewLove!.frame.width / 3, 30))
button.tag = number
button.setTitle(titleForButtonsOneSelected[number], forState: .Normal)
buttontitleLabel?.adjustsFontSizeToFitWidth = true
button.layer.borderWidth = 1.0
button.layer.borderColor = UIColor.blueColor().CGColor
button.backgroundColor = UIColor.clearColor()
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
view.addSubview(button)
return button
}
This way you have 3 different buttons in buttons. You can also customize the buttons right there as well.
Edit:
let buttons = Array(0...2).forEach {
let button = UIButton(frame: CGRectMake(CGFloat($0) * collectionViewLove!.frame.width / 3, 0, collectionViewLove!.frame.width / 3, 30))
button.tag = $0
button.setTitle(titleForButtonsOneSelected[$0], forState: .Normal)
buttontitleLabel?.adjustsFontSizeToFitWidth = true
button.layer.borderWidth = 1.0
button.layer.borderColor = UIColor.blueColor().CGColor
button.backgroundColor = UIColor.clearColor()
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
view.addSubview(button)
}
It looks like button[i]!.frame = CGRectMake(CGFloat(i) *(collectionViewLove?.frame.width)!/3,0,(collectionViewLove?.frame.width)!/3, 30) is producing the same frame each time, so your buttons will be superimposed on each other. You need to have something dynamic in your call to have them be in different spots and visible.

Cannot change textColor and font size inside the loop in swift

I have no idea why the font size and text Color doesn't takes any effect in the loop...anyone help??
Here is my code:
var buttons = ["N","F","S","D","C","A","R"]
for button in buttons
{
var Button:UIButton = UIButton()
Button = UIButton(frame: CGRect(x:10, y: 20, width: 80, height: 80))
Button.frame.origin = ButtonPosition
ButtonPosition.x = ButtonPosition.x + buttonIncrement
Button.layer.cornerRadius = 3
Button.clipsToBounds = true
Button.backgroundColor = UIColor.groupTableViewBackgroundColor()
Button.setTitle("\(button)", forState: UIControlState.Normal)
Button.titleLabel?.text = "\(button)"
Button.titleLabel?.font = UIFont(name:"Chalkboard SE Regular", size: 30)
Button.titleLabel?.textColor = UIColor.blackColor()
Button.setBackgroundImage(UIImage.imageWithColor(UIColor.colorWithHex("#b8b4af", alpha: 0.5)), forState: .Highlighted)
Button.addTarget(self, action: "check:", forControlEvents: UIControlEvents.TouchUpInside)
buttonView.addSubview(Button)
}
return buttonView
First remove the line Button.titleLabel?.text = "\(button)".
This one is enough Button.setTitle("\(button)", forState: UIControlState.Normal).
Then you should use setTitleColor method from a button to change it.
Button.setTitleColor(UIColor. blackColor(), forState: UIControlState.Normal)
Finally you made a mistake in the name of your font :
Button.titleLabel?.font = UIFont(name:"ChalkboardSE-Regular", size: 30.0)
That's it!
You should edit directly the button, not the titleLabel, like this:
Button.setTitle("\(button)", forState: .Normal)
Button.setTitleColor(UIColor.blackColor(), forState: .Normal)

Resources