Set Nav Bar's color without using .barTintColor? - swift

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
}

Related

How to hide /show multiple right button in the Navigation Bar swift 5

I need to hide the two right button in the Navigation Bar, then unhide it after the user selects some options.I added two buttons(i.e search and setting button) in the storyboard
Unfortunately, the following doesn't work:
navigationItem.rightBarButtonItem.isHidden = true
if I use below code then not able to show them again
navigationItem.rightBarButtonItem = nil
Add them programatically
class YourVC: UIViewController {
var item1 = UIBarButtonItem()
var item2 = UIBarButtonItem()
override func viewDidLoad() {
super.viewDidLoad()
let btn1 = UIButton()
btn1.setImage(UIImage(named: "validImage1"), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
item1.customView = btn1
let btn2 = UIButton()
btn2.setImage(UIImage(named: "validImage2"), for: .normal)
btn2.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
item2.customView = btn2
self.navigationItem.rightBarButtonItems = [item1,item2]
}
}
You can hide them:
self.navigationItem.rightBarButtonItems = nil
and show:
self.navigationItem.rightBarButtonItems = [item1,item2]

How to create overlapped bar button item programatically

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)

add gesture recognizer uivew navigation bar swift not working

I have a navigation controller with a navigation bar, I have added a UIView with subview of imageView and UILabel for titleView.
I need to be able to click on that view to do something else with addGestureRecognizer on that view but nothing is printed on the console.
The UIImageView has to be next to the UILabel
Here is the code I tried so far
private func setupNavBarWithUser() {
let titleView = UIView()
let width = titleView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)).width
titleView.frame = CGRect(origin:CGPoint.zero, size:CGSize(width: width, height: 500))
let profileImageView = UIImageView()
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
ImageService.getImage(withURL: NSURL(string: (user?.pictureURL)!)! as URL) { (image) in
profileImageView.image = image
}
titleView.addSubview(profileImageView)
profileImageView.leftAnchor.constraint(equalTo: titleView.leftAnchor).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: titleView.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
let nameLabel = UILabel()
titleView.addSubview(nameLabel)
nameLabel.text = user?.first_name
nameLabel.textColor = .white
nameLabel.translatesAutoresizingMaskIntoConstraints = false
nameLabel.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8).isActive = true
nameLabel.centerYAnchor.constraint(equalTo: profileImageView.centerYAnchor).isActive = true
nameLabel.rightAnchor.constraint(equalTo: titleView.rightAnchor).isActive = true
nameLabel.heightAnchor.constraint(equalTo: profileImageView.heightAnchor).isActive = true
titleView.centerXAnchor.constraint(equalTo: titleView.centerXAnchor).isActive = true
titleView.centerYAnchor.constraint(equalTo: titleView.centerYAnchor).isActive = true
self.navigationItem.titleView = titleView
let recognizer = UITapGestureRecognizer(target: self, action: #selector(self.testing))
titleView.isUserInteractionEnabled = true
titleView.addGestureRecognizer(recognizer)
}
#objc func testing() {
print("hello")
}
Hope someone can help me with this problem, much thank you !!
UPDATE this is where I need to add a gesture recognizer
Add this method in viewDidLoad/viewWillAppear
if let navigationBar = self.navigationController?.navigationBar {
// create a button
let button = UIButton(type: .custom)
button.frame = CGRect(x: navigationBar.frame.width/2-20, y: 0, width: 100, height: 40)
button.setTitleColor(.red, for: .normal)
button.setTitle("Button", for: .normal)
button.addTarget(self, action: #selector(self.testing), for: .touchUpInside)
// create a imageview
let profileImageView = UIImageView()
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
profileImageView.frame = CGRect(x: navigationBar.frame.width/2-60, y: 0, width: 40, height: 40)
profileImageView.image = UIImage(named: "heart")
// Add two elements to navigationbar
navigationBar.addSubview(profileImageView)
navigationBar.addSubview(button)
}

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
}

How to have a button call a method programmatically in a class in swift?

I want the button to slide off the screen when it's hit, but that part of the code (buttonPressed) isn't working. When the method buttonPressed is inside the class, nothing happens when the button is pressed. Move the method outside of the brackets (to right before viewDidLoad) and the code executes. However, then it slides the entire view as opposed to just the tutorial window. I either need to find a way to make buttonPressed work as a method of the Tutorial class, or find a way to make it refer to the specific instance of "view" that's called in the class.
I'm new to coding and very new to methods, so any help is appreciated!
class Tutorial{
var label = UILabel()
var view = UIView()
var button = UIButton()
init (text: String){
view = UIView()
label = UILabel(frame: CGRect(x: 10, y: 10, width: 180, height: 90))
button = UIButton(frame: CGRect(x: 50, y: 110, width: 100, height: 30))
view.backgroundColor = .white
view.layer.cornerRadius = 15
view.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .center
label.text = text
label.numberOfLines = 10
label.backgroundColor = .white
label.textColor = UIColor(red:0.12, green:0.15, blue:0.23, alpha:1.0)
button.backgroundColor = UIColor(red:0.23, green:0.72, blue:0.44, alpha:1.0)
button.setTitleColor(.white, for: .normal)
button.setTitle("Got it!", for: .normal)
button.layer.cornerRadius = 15
view.addSubview(label)
view.addSubview(button)
button.addTarget(self, action: #selector(buttonPressed), for: UIControlEvents.touchUpInside)
}
func setConstraints(height: CGFloat){
view.centerXAnchor.constraint(equalTo: view.superview!.centerXAnchor).isActive = true
view.topAnchor.constraint(equalTo: view.superview!.topAnchor, constant: UIScreen.main.bounds.height-300).isActive = true
view.widthAnchor.constraint(equalToConstant: 200).isActive = true
view.heightAnchor.constraint(equalToConstant: height).isActive = true
UIView.animate(withDuration: 0.5, delay: 0.2, options: [], animations: {
self.view.center.x -= UIScreen.main.bounds.width
})
}
#objc func buttonPressed(){
print("Pressed")
UIView.animate(withDuration: 0.5, delay: 0.0, options: [], animations: {
self.view.center.x -= UIScreen.main.bounds.width
},
completion: { (finished: Bool) in
self.view.isHidden = true
})
}
}
override func viewDidLoad() {
super.viewDidLoad()
let tutorial1 = Tutorial(text: "Click and hold to see the anatomy overlay")
self.view.addSubview(tutorial1.view)
tutorial1.setConstraints(height: 150)
Try using Interface Builder Constants. Here is the Apple Documentation. https://developer.apple.com/documentation/appkit/constants/interface_builder_constants?language=objc
make an IBOutlet and an IBAction for your button.