Adding image in the Navigation Bar - ios

I was wondering the best approach to put an image into the navigation bar.
My initial thought was to create a cocoa touch class for UINavigationController and set it up that way, but I can seem to get it to working using the below code:
class NavBarImage: UINavigationController {
override func awakeFromNib() {
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
self.setupView()
}
func setupView()
{
let navController = navigationController!
let image = #imageLiteral(resourceName: "BarTabsNavLogoWhite")
let imageView = UIImageView(image: image)
let bannerWidth = navController.navigationBar.frame.size.width
let bannerHeight = navController.navigationBar.frame.size.height
let bannerX = bannerWidth / 2 - image.size.width / 2
let bannerY = bannerHeight / 2 - image.size.height / 2
imageView.frame = CGRect(x: bannerX, y: bannerY, width: bannerWidth,
height: bannerHeight)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
}
I keep getting an "unexpectedly found nil while unwrapping an optional value" on let navController = navigationController!.
However, this method has also been working for me too. I created a cocoa touch class for UINavigationBar and used this code below:
import UIKit
class NavBarImg: UINavigationBar {
override init(frame: CGRect) {
super.init(frame: frame)
initialise()
}
required init(coder aDecoder: NSCoder){
super.init(coder: aDecoder)!
initialise()
}
func initialise(){
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 225, height: 40))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named:"BarTabsNavLogoWhite")
imageView.image = image
imageView.frame.origin = CGPoint(x: self.superview?.center.x, y: self.superview?.center.y)
addSubview(imageView)
}
}
The only problem with this is that on different iPhones I cant figure out how to get the image to always be centered on any device using CGPoint.
Then for the last method I found and implemented is done by the code below:
#IBDesignable class test: UINavigationBar { #IBInspectable var imageTitle: UIImage? = nil {
didSet {
guard let imageTitle = imageTitle else {
topItem?.titleView = nil
return
}
let imageView = UIImageView(image: imageTitle)
imageView.frame = CGRect(x: 0, y: 0, width: 40, height: 30)
imageView.contentMode = .scaleAspectFit
topItem?.titleView = imageView
}
}
}
I really like this method because with the IBDesignable function you can see it in the storyboard. However the way I have my viewcontrollers set up with tableviews, after i go past the first view controller, the navigation bar image disappears in all other view controllers when I run the simulator.
Looking for advice to see which method is the best approach and how to possibly solve the problems I am having. Or if anyone has a different method that they have found that works, id love to see how it works!

you can simply add a image or customize the barbutton as follows:
let button = UIButton(type: .custom)
button.setImage(UIImage(named: "icon_right"), for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 53, height: 31)
button.imageEdgeInsets = UIEdgeInsetsMake(-1, 32, 1, -32)//move image to the right
let label = UILabel(frame: CGRect(x: 3, y: 5, width: 20, height: 20))
label.font = UIFont(name: "Arial-BoldMT", size: 16)
label.text = "title"
label.textAlignment = .center
label.textColor = .black
label.backgroundColor = .clear
button.addSubview(label)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = barButton

Related

How to create Onboarding\Walkthrough swift

I'm trying to create a welcome onboarding for the first time users but none of the views are loafing in the simulator, all I'm getting is a red background when the onboardingVC gets presented. Can anyone see the issue as to why the titles, buttons, and images won't appear?
This is the message I'm getting in the console:
Warning: Attempt to present <EMA.WalkthroughVC: 0x7faa2401e5b0> on <EMA.HomeVC: 0x7faa22407e00> whose view is not in the window hierarchy!
FOUND ALL!!
let holderView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = true
view.backgroundColor = .darkGray
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
view.backgroundColor = UIColor.red
configure()
}
private func configure() {
let scrollView = UIScrollView(frame: holderView.bounds)
holderView.addSubview(scrollView)
let titles = ["Hi","Welcome","real nigga"]
for x in 0..<3 {
let pageView = UIView(frame: CGRect(x: CGFloat(x) * holderView.frame.size.width, y: 0, width: holderView.frame.size.width, height: holderView.frame.size.height))
scrollView.addSubview(pageView)
let label = UILabel(frame: CGRect(x: 10, y: 10, width: pageView.frame.size.width-20, height: 120))
let imageView = UIImageView(frame: CGRect(x: 10, y: 10+120+10, width: pageView.frame.size.width-20, height: pageView.frame.size.height - 60 - 130 - 15))
let button = UIButton(frame: CGRect(x: 10, y: pageView.frame.size.height - 60, width: pageView.frame.size.width-20, height: 50))
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
pageView.addSubview(label)
label.text = titles[x]
imageView.contentMode = .scaleAspectFill
imageView.image = UIImage(named: "BankCard\(x)")
pageView.addSubview(imageView)
button.setTitleColor(.red, for: .normal)
button.backgroundColor = .black
button.setTitle("Continue", for: .normal)
if x == 2 {
button.setTitle("Get Started", for: .normal)
}
button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
pageView.addSubview(button)
}
}
#objc func didTapButton(_ button: UIButton) {
}
}
"whose view is not in the window hierarchy"
you didn't add the views that you created to the main view try to add the subviews to the main by using this one
self.view.addSubview(holderView)
also don't forget to add the frame for the holder view like that
UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
view.translatesAutoresizingMaskIntoConstraints = true
and inside the view did load
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
self.view.addSubview(holderView)
}

Swift - response view in every view?

I've got a small question: is it possible somehow (without storyboard) to create a little view at the top of the screen (if there's a navigationbar, then under that), that displays errors / responses if needed?
Without creating views on every single viewController I made, just by code?
Or is there some extension you could recommend?
For example: "No Internet Connection"
You can check this answer - https://stackoverflow.com/a/49129636/6080920
Code required
extension UIViewController
{
func showNotificationView(message : String)
{
//base View
let baseView = UIView(frame: CGRect(x: 20, y: self.view.frame.size.height-(self.view.frame.size.height*0.15), width: self.view.frame.size.width-40, height: self.view.frame.size.height*0.08))
baseView.backgroundColor = UIColor.gray
baseView.clipsToBounds=true
self.view.addSubview(baseView)
//Image View
let imageView = UIImageView(image: UIImage(named: "RM_3"))
imageView.clipsToBounds=true
imageView.frame = CGRect(x: 0, y: 0, width: baseView.frame.size.width*0.2, height: baseView.frame.size.height)
baseView.addSubview(imageView)
//Label
let textLabel = UILabel(frame: CGRect(x: baseView.frame.size.width*0.2+10, y: 0, width: baseView.frame.size.width, height: baseView.frame.size.height))
textLabel.textColor = UIColor.white
textLabel.backgroundColor = UIColor.clear
textLabel.textAlignment = .left;
textLabel.numberOfLines = 0
textLabel.font = UIFont(name: "Montserrat-Light", size: 12.0)
textLabel.text = message
baseView.addSubview(textLabel)
}
}
Usage
#IBAction func navigate(_ sender: Any) {
self.showNotificationView(message: "hihihihh")
}

Swift Custom Navigation Controller Class

Everyone who reads it, hello and thank you. I am writing an application like Viber or WhatsApp for iOS devices using Xcode 8.2.1 and Swift 3.0. I have a problem: I want my app has a navigation controller but not a simple one, I want it to be a custom one. There is a print screen from WhatsApp to be understanding, what I am trying to achieve:
As we can see, this navigation controller has 3 buttons, label and image with avatar. I also want to change my color to green one. Due to do this I have created class:
import UIKit
class CustomNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.barTintColor = UIColor.green
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 39, height: 39))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "logo")
imageView.image = image
navigationItem.titleView = imageView
}
}
And it gives this result:
As you can see it is without picture. I know that if I add this code:
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 39, height: 39))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "logo")
imageView.image = image
navigationItem.titleView = imageView
to ViewController, image with logo will appear but I want complete class which I will connect somewhere (for example, in Interface Builder) and it will make a beautiful Navigation Controller with buttons, images and etc. Moreover, I can create a different class with another Navigation Controller and connect it to different screens, on which, for example, I will not need images, only buttons. So question is: how to make custom Navigation Controller class?
I will be really glad and thankful for any help, Thank You!
Now, I know the answer! It will be written for Swift 4.1.2. Each class inherited from UIViewController has a property self.navigationController?.navigationBar or navigationItem. You can create you own class like this:
class CustomNavigationController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let color = UIColor(red: 81 / 255, green: 155 / 255, blue: 22 / 255, alpha: 1.0)
self.navigationController?.navigationBar.barTintColor = color
let image = UIImage(named: "logo")
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
}
private func imageView(imageName: String) -> UIImageView {
let logo = UIImage(named: imageName)
let logoImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 35, height: 35))
logoImageView.contentMode = .scaleAspectFit
logoImageView.image = logo
logoImageView.widthAnchor.constraint(equalToConstant: 35).isActive = true
logoImageView.heightAnchor.constraint(equalToConstant: 35).isActive = true
return logoImageView
}
func barImageView(imageName: String) -> UIBarButtonItem {
return UIBarButtonItem(customView: imageView(imageName: imageName))
}
func barButton(imageName: String, selector: Selector) -> UIBarButtonItem {
let button = UIButton(type: .custom)
button.setImage(UIImage(named: imageName), for: .normal)
button.frame = CGRect(x: 0, y: 0, width: 35, height: 35)
button.widthAnchor.constraint(equalToConstant: 35).isActive = true
button.heightAnchor.constraint(equalToConstant: 35).isActive = true
button.addTarget(self, action: selector, for: .touchUpInside)
return UIBarButtonItem(customView: button)
}
}
Now you can inherit any of you UIViewControllers from this class CustomNavigationController and add ass much buttons, icons, change colors, logos and etc. as much as you want (of course, in normal range)! Like this:
class ViewController: CustomNavigationController {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = barImageView(imageName: "picture1")
let firstImage = barImageView(imageName: "picture2")
let secondButton = barButton(imageName: "picture3", selector: #selector(secondButtonPressed))
navigationItem.rightBarButtonItems = [firstImage, secondButton]
}
#objc func secondButtonPressed() {
print("Pressed")
}
}
This is my solution, maybe not the best, but 100% works! Thank you!

Xcode 7.3.1 : Set background image to UINavigationBar and display back button

I want to set logo of app as background image to UINavigationBar and when user traverse into app it should display logo as well as back button on top of it.
Below is code that I've used :
func setNavigationBar() {
let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height
let screenSize: CGRect = UIScreen.mainScreen().bounds
let objCustomView = CustomView(frame: CGRect(x: 0, y: 0, width: screenSize.width, height: navigationBarHeight))
let objWindow = UIApplication.sharedApplication().keyWindow
objWindow?.addSubview(objCustomView)
self.navigationItem.setHidesBackButton(false, animated:true);
self.navigationItem.backBarButtonItem = UIBarButtonItem(title:"", style:.Plain, target:nil, action:nil)
}
The issue with this is that back button goes behind the image.
How to fix this?
After refering post by #NDoc I'm getting extra space in left. Why so?
Also, the back button should be white with no back text i.e. only < arrow.
Below is code for customView :
class CustomView: UIView {
var imgLogo = UIImageView(frame:CGRectZero)
override init(frame: CGRect) {
super.init(frame: frame)
let screenSize: CGRect = UIScreen.mainScreen().bounds
imgLogo.frame = CGRectMake(0, 0, screenSize.width, 44.0)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup() {
imgLogo.image = UIImage(named:"BoM_Logo")
self.addSubview(imgLogo)
}
}
You can display your logo in leftBarButtonItem and set the leftItemsSupplementBackButton to true to display backButton also like this.
let logoView = UIImageView(frame: CGRect(x: 0, y: 0, width: 60, height: 30))
logoView.image = UIImage(named: "Logo")
let item = UIBarButtonItem(customView: logoView)
self.navigationItem.leftBarButtonItem = item
To show the back button with your logo image set leftItemsSupplementBackButton to true
self.navigationItem.leftItemsSupplementBackButton = true
Edit:
If you want custom arrow then you need to use leftBarButtonItems and pass array of BarButtonItem and no need to set leftItemsSupplementBackButton to true like this.
let logoView = UIImageView(frame: CGRect(x: 0, y: 0, width: 60, height: 30))
logoView.image = UIImage(named: "Logo")
let logoItem = UIBarButtonItem(customView: logoView)
let btnBack = UIButton(frame: CGRect(x: 0, y: 0, width: 25, height: 25))
btnBack.setImage(UIImage(named: "Back_Arrow"), forState: .Normal)
btnBack.addTarget(self, action: #selector(self.buttonAction(_:)), forControlEvents: .TouchUpInside)
let backItem = UIBarButtonItem(customView: btnBack)
self.navigationItem.leftBarButtonItems = [backItem, logoItem]
Note: Don't forgot to add buttonAction action method inside your viewController.
Try this in your appDelegate
let image = UIImage.init(named:"upper-bar.png")
UINavigationBar.appearance().setBackgroundImage(image,forBarMetrics:UIBarMetrics.Default)
for back button try this in the viewDidLoad() of your viewController
let image1 = UIImage(named: "go10.png") as UIImage?
let btnLeft = UIButton(type: .Custom)
btnLeft.frame = CGRectMake(0, 0, 25, 25)
btnLeft.setImage(image1,forState:UIControlState.Normal)
btnLeft.addTarget(self, action:(#selector(NameofyourViewController.backBtn(_:))),forControlEvents:UIControlEvents.TouchUpInside)
let leftBarButton = UIBarButtonItem(customView: btnLeft)
self.navigationItem.leftBarButtonItem = leftBarButton
#IBAction func backBtn(sender: UIButton)
{
self.navigationController?.popViewControllerAnimated(true)
}

How to create custom view programmatically in swift having controls text field, button etc

I am trying to access the MyCustomView from another class using the following code in ViewController.swift ..
var view = MyCustomView(frame: CGRectZero)
.. in the viewDidLoad method. The problem is the view does not get initialized in the simulator.
I have already set class in storyboard for the current ViewController.
class MyCustomView: UIView {
var label: UILabel = UILabel()
var myNames = ["dipen","laxu","anis","aakash","santosh","raaa","ggdds","house"]
override init(){
super.init()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.addCustomView()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func addCustomView() {
label.frame = CGRectMake(50, 10, 200, 100)
label.backgroundColor=UIColor.whiteColor()
label.textAlignment = NSTextAlignment.Center
label.text = "test label"
label.hidden=true
self.addSubview(label)
var btn: UIButton = UIButton()
btn.frame=CGRectMake(50, 120, 200, 100)
btn.backgroundColor=UIColor.redColor()
btn.setTitle("button", forState: UIControlState.Normal)
btn.addTarget(self, action: "changeLabel", forControlEvents: UIControlEvents.TouchUpInside)
self.addSubview(btn)
var txtField : UITextField = UITextField()
txtField.frame = CGRectMake(50, 250, 100,50)
txtField.backgroundColor = UIColor.grayColor()
self.addSubview(txtField)
}
The CGRectZero constant is equal to a rectangle at position (0,0) with zero width and height. This is fine to use, and actually preferred, if you use AutoLayout, since AutoLayout will then properly place the view.
But, I expect you do not use AutoLayout. So the most simple solution is to specify the size of the custom view by providing a frame explicitly:
customView = MyCustomView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
self.view.addSubview(customView)
Note that you also need to use addSubview otherwise your view is not added to the view hierarchy.
Swift 3 / Swift 4 Update:
let screenSize: CGRect = UIScreen.main.bounds
let myView = UIView(frame: CGRect(x: 0, y: 0, width: screenSize.width - 10, height: 10))
self.view.addSubview(myView)
var customView = UIView()
#IBAction func drawView(_ sender: AnyObject) {
customView.frame = CGRect.init(x: 0, y: 0, width: 100, height: 200)
customView.backgroundColor = UIColor.black //give color to the view
customView.center = self.view.center
self.view.addSubview(customView)
}
let viewDemo = UIView()
viewDemo.frame = CGRect(x: 50, y: 50, width: 50, height: 50)
self.view.addSubview(viewDemo)
view = MyCustomView(frame: CGRectZero)
In this line you are trying to set empty rect for your custom view. That's why you cant see your view in simulator.

Resources