How to create overlapped bar button item programatically - swift

I know how to create overlap shopping cart and quantity label with xib using uiimage like this
Now i'm trying to create overlap bar button items programatically but cannot figure out how to position the elements. My attempt:
My current code for bar button items:
let button: UIButton = UIButton(frame: CGRect(x: 0.0,
y: 0.0,
width: 24.0,
height: 24.0))
button.setImage(UIImage(named: "my cart", in: nil, compatibleWith: nil), for: .normal)
button.addTarget(self, action: #selector(cartButtonDidTapped), for: .touchUpInside)
let shoppingCartButton: UIBarButtonItem = UIBarButtonItem(customView: button)
shoppingCartQuantityLabel.layer.cornerRadius = 10
shoppingCartQuantityLabel.layer.masksToBounds = true
shoppingCartQuantityLabel.textColor = .white
shoppingCartQuantityLabel.backgroundColor = .red
shoppingCartQuantityLabel.textAlignment = .center
let shoppingCartQuantityLabelItem: UIBarButtonItem = UIBarButtonItem(customView: shoppingCartQuantityLabel)
navigationItem.rightBarButtonItems = [shoppingCartQuantityLabelItem, shoppingCartButton]

Idea here is to add the label as subview inside the button. You can adjust the label as per your needs from the below example,
let button: UIButton = UIButton(frame: CGRect(x: 0.0, y: 0.0, width: 24.0, height: 24.0))
button.setImage(#imageLiteral(resourceName: "my cart"), for: .normal)
let label = UILabel(frame: .init(origin: .init(x: 20, y: -8), size: .init(width: 20, height: 20)))
label.text = "12"
label.textAlignment = .center
label.textColor = .white
label.font = .systemFont(ofSize: 10)
label.backgroundColor = .red
label.layer.cornerRadius = 10
label.clipsToBounds = true
button.addSubview(label)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)

You can use this code snippet also from Github: https://gist.github.com/freedom27/c709923b163e26405f62b799437243f4#gistcomment-2236010
then set badge to your last right bar button item as below
navigationItem.rightBarButtonItems = [shoppingCartButton]
let lastBarButton = navigationItem.rightBarButtonItems?.last
lastBarButton?.setBadge(text: "10", withOffsetFromTopRight: CGPoint(x: 38, y: -3), andColor: UIColor.red, andFilled: true, andFontSize: 12)

Related

Swift 5: My barbutton in navigationbar wasn't fit

Here is my image:
And I put it in rightbarbuttonitem, and it is not fit with area.
This is result
Here is my code:
let button = UIButton(type: .custom)
button.setImage(UIImage (named: "Group 4"), for: .normal)
button.frame = CGRect(x: 0.0, y: 0.0, width: 35, height: 35)
//button.addTarget(target, action: nil, for: .touchUpInside)
let barButtonItem = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = barButtonItem
Please help me!!!
Can you try this instead of your code?
let rightBarButtonItem = UIButton(frame: CGRect(x: 0, y: 0, width: 36, height: 36))
rightBarButtonItem.setBackgroundImage(UIImage(named: "Group 4"), for: .normal)
rightBarButtonItem.addTarget(self, action: #selector(actionRightBar), for: .touchUpInside)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: rightBarButtonItem)

Nav bar cuts view on dismiss view controller on iPhone XS Max swift

I have two view controllers, VC1 and VC2, First I present VC1 and programmatically create Nav Bar and place two buttons in that, after that I present VC2 and the same I create navbar programmatically. Now when i dimiss VC2 to VC1 it cuts the view to half of navbar and button also get cutoff. I have tried different solutions but not getting it fixed. I'm confused why it is cutting the view? This is my code to create navbar in VC1,
let width = self.view.frame.width
let navigationBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 20, width: width, height: 64))
UINavigationBar.appearance().barTintColor = .white
UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().isTranslucent = false
self.view.addSubview(navigationBar);
let navigationItem = UINavigationItem(title: "Owners")
self.title = "Owners"
let cancelBtn = UIButton()
let searchBtn = UIButton()
cancelBtn.setImage(UIImage.init(named: "cancelBtn")?.tint(with: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)), for: .normal)
cancelBtn.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
cancelBtn.addTarget(self, action: #selector(onTapBack), for: .touchUpInside)
let suggestButtonContainer = UIView(frame: cancelBtn.frame)
suggestButtonContainer.addSubview(cancelBtn)
searchBtn.setImage(Icon.cm.search?.tint(with: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)), for: .normal)
searchBtn.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
searchBtn.addTarget(self, action: #selector(onTapSearch), for: .touchUpInside)
let searchView = UIView(frame: searchBtn.frame)
searchView.addSubview(searchBtn)
let searchButtonItem = UIBarButtonItem(customView: searchView)
let suggestButtonItem = UIBarButtonItem(customView: suggestButtonContainer)
navigationItem.leftBarButtonItem = suggestButtonItem
navigationItem.rightBarButtonItem = searchButtonItem
navigationBar.setItems([navigationItem], animated: false)
and this is how i create VC2 navbar,
let width = self.view.frame.width
let navigationBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 25, width: width, height: 64))
UINavigationBar.appearance().barTintColor = .white
UINavigationBar.appearance().tintColor = .white
UINavigationBar.appearance().isTranslucent = false
self.view.addSubview(navigationBar);
let navigationItem = UINavigationItem(title: "Owners")
self.title = "Owners"
let cancelBtn = UIButton()
cancelBtn.setImage(UIImage.init(named: "cancelBtn")?.tint(with: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)), for: .normal)
cancelBtn.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
cancelBtn.addTarget(self, action: #selector(onTapBack), for: .touchUpInside)
let suggestButtonContainer = UIView(frame: cancelBtn.frame)
suggestButtonContainer.addSubview(cancelBtn)
let suggestButtonItem = UIBarButtonItem(customView: suggestButtonContainer)
navigationItem.leftBarButtonItem = suggestButtonItem
navigationBar.setItems([navigationItem], animated: false)
Now when is dismiss from VC2 to VC1 it shows navbar like this,
I think the problem come from the status bar height.
20pt for iPhone 6, 7, 8, ..., and 44pt for iPhones with a notch.
try to set the navigation bar frame origin.y to UIApplication.shared.statusBarFrame.height
let navigationBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: UIApplication.shared.statusBarFrame.height, width: width, height: 64))

Set Nav Bar's color without using .barTintColor?

I am trying to display a user picture in place of the rightBarButton but setting barTintColor of the UINavigationBar tints the image.
In the AppDelegate, tried:
UINavigationBar.appearance().barTintColor = .blue
In the viewDidLoad, tried:
self.navigationController?.navigationBar.backgroundColor = .blue
self.navigationController?.navigationBar.tintColor = .blue
self.navigationController?.navigationBar.barTintColor = .blue
To set the image:
let avatarBtn = UIButton(type: .custom)
avatarBtn.frame = CGRect(x: 0.0, y: 0.0, width: 30, height: 30)
avatarBtn.setImage(UIImage(named:"myAvatar")?.withRenderingMode(.alwaysOriginal), for: .normal)
let menuBarItem = UIBarButtonItem(customView: avatarBtn)
menuBarItem.tintColor = .clear
self.navigationItem.rightBarButtonItem = menuBarItem
None of these have worked. How can you setup a multi-colored nav bar button without a tint?
Thanks in advance
Change tintColor.
tintColor : The tint color to apply to the navigation items and bar button items.
I used your code but in my case i got expected result. Which image type you are using?
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.backgroundColor = .blue
self.navigationController?.navigationBar.tintColor = .blue
self.navigationController?.navigationBar.barTintColor = .blue
let avatarBtn = UIButton(type: .custom)
avatarBtn.frame = CGRect(x: 0.0, y: 0.0, width: 30, height: 30)
avatarBtn.setImage(UIImage(named:"myAvatar1")?.withRenderingMode(.alwaysOriginal), for: .normal)
let menuBarItem = UIBarButtonItem(customView: avatarBtn)
menuBarItem.tintColor = .clear
self.navigationItem.rightBarButtonItem = menuBarItem
}

Stackview in navigation bar

Is it possible to place UIStackView in NavigationBar programmaticaly using swift? I want to place there StackView with two arranged stackviews. But when i do that , it shows nothing in navigation bar. If it is possible, please provide example. Thanks
Finally I found solution
let btnSort = UIButton(type: .system)
btnSort.frame = CGRect(x: 0, y: 0, width: 120, height: 40)
btnSort.tintColor = UIColor.white
btnSort.setImage(UIImage(named:"ic_controls_icon.png"), for: .normal)
btnSort.imageEdgeInsets = UIEdgeInsets(top: 6,left: -10,bottom: 6,right: 34)
btnSort.titleEdgeInsets = UIEdgeInsets(top: 0,left: 0,bottom: 0,right: 14)
btnSort.setTitle("SORT", for: .normal)
btnSort.layer.borderWidth = 1.0
btnSort.backgroundColor = UIColor.red //--> set the background color and check
btnSort.layer.borderColor = UIColor.white.cgColor
let btnControl = UIButton(type: .system)
btnControl.frame = CGRect(x: 0, y: 0, width: 120, height: 40)
btnControl.tintColor = UIColor.white
btnControl.setImage(UIImage(named:"ic_controls_icon.png"), for: .normal)
btnControl.imageEdgeInsets = UIEdgeInsets(top: 6,left: -10,bottom: 6,right: 34)
btnControl.titleEdgeInsets = UIEdgeInsets(top: 0,left: 0,bottom: 0,right: 14)
btnControl.setTitle("SORT", for: .normal)
btnControl.layer.borderWidth = 1.0
btnControl.backgroundColor = UIColor.red //--> set the background color and check
btnControl.layer.borderColor = UIColor.white.cgColor
let view = UIStackView(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
view.axis = .horizontal
view.distribution = .fillEqually
view.spacing = 5
view.addArrangedSubview(btnSort)
view.addArrangedSubview(btnControl)
let mainTitleView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 50))
mainTitleView.addSubview(view)
navigationItem.titleView = mainTitleView
You can make any UIView subclass (of which UIStackView is one) the navigation bar's title using your view controller's navigationItem.titleView property.
You can test this out in a playground…
import UIKit
import PlaygroundSupport
let vc = UIViewController()
vc.view.backgroundColor = .white
let nav = UINavigationController(rootViewController: vc)
let topLabel = UILabel()
topLabel.font = UIFont.boldSystemFont(ofSize: 20)
topLabel.text = "Hello"
let bottomLabel = UILabel()
bottomLabel.font = UIFont.systemFont(ofSize: 16)
bottomLabel.text = "World!"
let stackView = UIStackView(arrangedSubviews: [topLabel, bottomLabel])
stackView.axis = .vertical
vc.navigationItem.titleView = stackView
PlaygroundPage.current.liveView = nav.view
PlaygroundPage.current.needsIndefiniteExecution = true
var navTitle: String? = "Preview Checklist"
var navSubTitle: String? = "Edit Checklist >"
lazy var titleStackView: UIStackView = {
let titleLabel = UILabel()
titleLabel.textAlignment = .left
titleLabel.text = navTitle
//titleLabel.font = UIFont(name: "RawlineMedium-Regular", size:CGFloat(15))
titleLabel.textColor = .white
let subtitleLabel = UILabel()
subtitleLabel.textAlignment = .left
subtitleLabel.text = navSubTitle
//subtitleLabel.font = UIFont(name: "RawlineMedium-Regular", size:CGFloat(11))
subtitleLabel.textColor = .white
let stackView = UIStackView(arrangedSubviews: [ titleLabel, subtitleLabel])
stackView.axis = .vertical
stackView.backgroundColor = .blue
return stackView
}()
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.titleView = titleStackView
}

Vertically align bar buttons inside toolbar

I am currently using the following code to display a datepicker when a user clicks on a UITextfield. This works fine, but the problem is there left and right button are not properly vertically center aligned. Is there any way to accomplish this? I tried using UIOffset on the buttons but without result.
private func setupDatePicker() {
let toolBar = UIToolbar(frame: CGRect(x: 0, y: self.view.frame.size.height/6,
width: self.view.frame.size.width, height: 40.0))
toolBar.layer.position = CGPoint(x: self.view.frame.size.width/2, y: self.view.frame.size.height-20.0)
toolBar.barStyle = UIBarStyle.blackTranslucent
toolBar.tintColor = UIColor.white
toolBar.backgroundColor = UIColor.black
let cancelBtn = UIBarButtonItem(title: "cancel".localized(lang: Localize.currentLanguage()), style: UIBarButtonItemStyle.plain, target: self,
action: #selector(tapppedToolBarBtn))
let okBarBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self,
action: #selector(donePressed))
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace,
target: self, action: nil)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width / 3,
height: self.view.frame.size.height))
label.font = UIFont(name: "Roboto-Regular", size: 12)
label.backgroundColor = UIColor.clear
label.textColor = UIColor.white
label.text = "selectdate".localized(lang: Localize.currentLanguage())
label.textAlignment = NSTextAlignment.center
let textBtn = UIBarButtonItem(customView: label)
toolBar.setItems([cancelBtn, flexSpace, textBtn, flexSpace, okBarBtn], animated: true)
startDateTxf.inputAccessoryView = toolBar
}
The result :
Result of the datepicker toolbar
I managed to fix this alignment issue by using the following code :
let toolBar = UIToolbar(frame: CGRect(x: 0, y: self.view.frame.size.height/6,
width: self.view.frame.size.width, height: 40.0))
toolBar.layer.position = CGPoint(x: self.view.frame.size.width/2, y: self.view.frame.size.height-20.0)
toolBar.barStyle = UIBarStyle.blackTranslucent
toolBar.tintColor = UIColor.white
toolBar.backgroundColor = UIColor.black
let cancelBtn1 = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width / 4,
height: self.view.frame.size.height))
cancelBtn1.setTitle("cancel".localized(lang: Localize.currentLanguage()), for: .normal)
cancelBtn1.addTarget(self, action: #selector(tapppedToolBarBtn), for: .touchUpInside)
let cancelBtn = UIBarButtonItem(customView: cancelBtn1)
let okBarBtn1 = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width / 4,
height: self.view.frame.size.height))
okBarBtn1.setTitle("Done", for: .normal)
okBarBtn1.addTarget(self, action: #selector(donePressed(sender:)), for: .touchUpInside)
let okBarBtn = UIBarButtonItem(customView: okBarBtn1)
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace,
target: self, action: nil)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width / 3,
height: self.view.frame.size.height))
label.font = UIFont(name: "Roboto-Regular", size: 12)
label.backgroundColor = UIColor.clear
label.textColor = UIColor.white
label.text = "selectdate".localized(lang: Localize.currentLanguage())
label.textAlignment = NSTextAlignment.center
let textBtn = UIBarButtonItem(customView: label)
toolBar.setItems([cancelBtn, flexSpace, textBtn, flexSpace, okBarBtn], animated: true)
startDateTxf.inputAccessoryView = toolBar
The result is : result in simulator