How to add custom view in navigation bar? - ios

I want to create the custom view on my navigation bar.I have three items on the navigation bar.On the left i want to add UIImageView just after that a UILabel & to the right a UIImage.Now i have added right bar button to the right from storyboard & added image.I want to add Imageview & UILabel to the left side.Please tell how can i add this so that gap is maintained properly.

//FETECH BUTTON IMAGES FOR BOTH STATES NORMAL AND SELECTED
var normal= UIImage(contentsOfFile:NSBundle.mainBundle().pathForResource("FIRSTBUTTONIMG", ofType: ".png" , inDirectory: "FOLDER_PATH")!);
normal = normal?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
var selected = UIImage(contentsOfFile:NSBundle.mainBundle().pathForResource("FIRSTBUTTONIMGSELECTED ", ofType: ".png" , inDirectory: "FOLDER_PATH")!);
selected = selected?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
let Fbutton = UIButton(type: .Custom);
Fbutton.setImage(normal, forState: UIControlState.Normal)
Fbutton.setImage(selected, forState: UIControlState.Selected)
Fbutton.addTarget(self, action:#selector(YOURBTNACTION(_:)), forControlEvents: .TouchUpInside)
Fbutton.frame=CGRectMake(0, -6, 53, 53)
//ADD YOUR CUSTOM VIEW AND ADD ABOVE BUTTON INSIDE CUSTOM VIEW
let CustomView = UIView()
CustomView.frame=CGRectMake(0, 0, Fbutton.frame.height, Fbutton.frame.width);
CustomView.addSubview(Button)
//ADD MORE ITEMS TO CUSTOM VIEW IF NEEDED
//ADD THAT CUSTOM VIEW TO UIBarButtonItem
let CustomViewButton:UIBarButtonItem = UIBarButtonItem(customView: backCustomView)
//ASSIGN THAT UIBarButtonItem TO leftBarButtonItems AS ARRAY ITEM
self.navigationItem.leftBarButtonItems=[CustomViewButton,MORE ITEM IF NEEDED];

Related

show title and image in navigation bar button

I would like to show the button and image in the navigation bar.
Using this
let action = UIAction { _ in }
let image = UIImage(named: "logout")
let doneButton = UIBarButtonItem(title: "Done", image: image, primaryAction: action, menu: menu)
navigationItem.leftBarButtonItem = doneButton
Just shows the image without the title.
The documentation
https://developer.apple.com/documentation/uikit/uibarbuttonitem/3600776-init
Only indicates that if title is nil it would not be displayed.
I tried
https://stackoverflow.com/a/54403576/1898829 same result
https://stackoverflow.com/a/3903348/1898829 one loses a lot of default behaviour and cant use the uiaction with the new apis.
While I can definitely find a work around but any work around is less than ideal.
UIBarButtonItem doesn't support both text and image in the same UIBarButtonItem. There are 3 approach to solve this problem:
Make your self a custom navigation controller
Make an image which combine both your text and your image
Make your text and image into a custom view. UIBarButtonItem support a custom View. Check example below for how to use. You can customize the View both in coding or using autolayout view for your choice
let view = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 50, height: 50)))
let gesture = UITapGestureRecognizer(target: self, action: #selector(tapInView))
view.addGestureRecognizer(gesture)
view.backgroundColor = .red
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: view)
#objc func tapInView() {
print("tap")
}

iOS 11 - Cannot access UIView of UIBarButton

I am trying to create a badge number on the top right corner of my UIBarButton. For iOS 9 and 10 it works fine but with iOS 11 I cannot access the view of the button which I normally do like this:
extension UIBarButtonItem {
func createBadge() {
guard let view = self.value(forKey: "view") as? UIView else {
return
}
}
}
I understand that using key values is not a good idea for cases like this, as the key can change. But is there an alternative here, using public APIs so that the solution works for iOS 11 too?
Thanks.
You can create the UIBarButtonItem from a custom view. Add the badge to the custom view
I'd recommend to use a custom view and embed it in your UIToolbar / UINavigationBar instead of a UIBarbuttonItem
The custom view could contain a UIButton and your badge view.
Via storyboard, simply drag and drop a UIView to the slot in your bar and add a UIButton as subview. Depending on your implementation of a badge, you could just create a UILabel and position it via constraints relative to your UIButton.
Create IBOutlets for those and set them up programmatically.
let button = UIButton.init(frame: CGRect.init(x: 0, y: 0, width: 25, height: 25))
button.addTarget(self.target, action: self.action!, for: UIControlEvents.touchUpInside)
button.target(forAction: self.action!, withSender: self.target)
button.setImage(self.image, for: .normal)
self.customView = button
guard let view = self.value(forKey: "view") as? UIView else {
return
}

Swift - Adding touch to UIImageView

I'm following a tutorial online and I'm trying to add touch detection to an UIImageView. I realize that this can be done with a gesture recognizer but I have a different problem and I don't know how to ask for it.
Basically, I added an overlay UIButton initialized from the frame of imageView. However, I have to move the frame down 64 px because of the navigation bar. My imageView is added form the storyboard but UIButton is added programmatically.
Is there a way to do this without adding 64 px manually? This is no biggies but since the frame of the imageView when printing is (10, 10, 355, 450) and the frame of UIButton is (10, 74, 355, 450), it kinda ticks me off a little bit.
Let me clarify, I'm wondering why view controller doesn't take into account the size of the navigation bar when adding subview programmatically? It seems to handle this just fine when adding subview from Storyboard.
Without adding 64px:
overlay = UIButton(frame: imageView.frame)
overlay.backgroundColor = UIColor.red
overlay.addTarget(self, action: #selector(imageViewTapped), for: .touchUpInside)
view.addSubview(overlay)
With 64px added - fits perfectly
overlay = UIButton(frame: imageView.frame.offsetBy(dx: 0, dy: 64))
overlay.backgroundColor = UIColor.red
overlay.addTarget(self, action: #selector(imageViewTapped), for: .touchUpInside)
view.addSubview(overlay)
You can add button on image view.
Try This :
let overlay = UIButton(frame: imageView.bounds)
imageView.isUserInteractionEnabled = true
overlay.backgroundColor = UIColor.red.withAlphaComponent(0.3)
overlay.addTarget(self, action: #selector(imageViewTapped), for: .touchUpInside)
imageView.addSubview(overlay)
You can use UITapGestureRecognizer for the same as given below.
let bg = UIImageView(image: UIImage(named: "Home"))
bg.frame = self.view.frame
self.view.addSubview(bg)
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(SecondViewController.onTapScreen))
bg.isUserInteractionEnabled = true
bg.addGestureRecognizer(tapRecognizer)
Handle tap event as given below
func onTapScreen() {
// Handle touch here.
}
By this way you don't need to use button also so it can avoid multiple controls.
Set your UIViewController's navigationbar to Opaque Navigation Bar. It will start you view below navigation bar.

How to make one UIButton, UILabel, & UITextField control all input

Currently I am working on my first iOS app, a ToDo Planner. Here is the layout for it.
Right now I have it set up in that each line has its own textField, button (checkmarked circle), and label (strike line). Like this:
if(textField == textField1) // if the first text field is pressed
{
let image = UIImage(named: "To Be Completed Circle.png")
button1 = UIButton(frame: CGRect(x: 340, y: 56, width: 30, height: 30));
button1.setBackgroundImage(image, for: UIControlState.normal)
self.view.addSubview(button1)
button1.addTarget(self, action:#selector(self.pressCheck), for: .touchUpInside)
}
And this:
if(button == button1) // if first button was pressed
{
button1.setBackgroundImage(image, for: UIControlState.normal) //set image to be of circle with checkmark
button1.removeTarget(nil, action: nil, for: .allEvents) //remove old target action
button1.addTarget(self, action:#selector(self.pressUnCheck), for: .touchUpInside) //add new target action for removing checkmark
self.view.addSubview(button1)
textField1.textColor = UIColor.gray //change textfield to a gray color
label1 = UILabel(frame: CGRect(x : 34, y : 70, width: 200, height: 2)) //add the strike line through textfield
label1.backgroundColor = UIColor(patternImage: labelImage!)
self.view.addSubview(label1)
}
Button1 Label1 textfield1 all correspond to the first line of input.
Button2 Label2 textfield2 etc...
The textfields were made using interface builder, the buttons/labels were made programmatically. I was wondering if there is any way (I'm sure there is) to use just one button one label and one textfield to control all user input? The buttons and labels all essentially to the same thing.
Let me know if I'm not too clear.
You can use a TableView with custom cells for your each line. A single cell can be designed with your required Label, TextField and Button. You can make it through the storyboard itself using prototype cell in tableView.
This should really be using a TableView.
That would allow you to set up one row of the table with the elements you want and reuse them the way you are asking about.
You should create a nib file of UITableViewCell class where you can design a single cell with Textfield, label, button. And you should use UITableview on storyboard and after that you should load that nib.

remove gap between buttons in navigation item rightbuttonitems

I'm using self.navigationItem.rightBarButtonItems to setup my navigation bar items. However, for the bar buttons, i'm using a custom view(button). I observe there is spacing between buttons. How can I remove this?
i know its too late, but i solved it using following method of UIBarButtonItem
use
[barbuttonitem setImageInsets:UIEdgeInsetsMake(0, -30, 0, -70)];
I solved this by using storybord interface.I know you are using custom Bar,but this answer will useful for those who use stroybord.
1.Select the Bar item.
2.Select the Size Inspector.
Here you can find image Inset,using top,bottom AND left , right you can change the position of Bar Item.
You can't remove it. You can work around it by creating a bar button item with a custom view, where that custom view has you custom buttons all added as subviews. In this way you can directly control the exact positioning.
Here is an example that how you can resolve this issue:
Create an extension of UIBarButton
extension UIBarButtonItem
{
/** Create custom right bar button for reduce space between right bar buttons */
func initRightButton(let imageNamed:String, let target:UIViewController, let selector:Selector) -> UIBarButtonItem {
let frame = CGRectMake(0, 0, 30, 30)
//Create imageView
let imageView = UIImageView(frame:frame)
imageView.image = UIImage(named: imageNamed)
//Create Button
let button = UIButton(frame: frame)
button.addTarget(target, action: selector, forControlEvents: .TouchUpInside)
//Create View and add imageView and Button
let view = UIView(frame: frame)
view.addSubview(imageView)
view.addSubview(button)
return UIBarButtonItem(customView: view)
}
}
In your class controller use the method customizeNavigationBar
func customizeNavigationBar() {
//Create custom right bar button chat for reduce space between right bar buttons
let barButton1 = UIBarButtonItem().initRightButton("customImageNamed1", target: self, selector: customSelector)
let barButton2 = UIBarButtonItem().initRightButton("customImageNamed2", target: self, selector: customSelector)
self.navigationItem.rightBarButtonItems = [barButton1,barButton2]
}

Resources