UIBarButtonItem: Image offsets - ios

I am trying to create custom back bar button item using image. I've done it this way:
let image = UIImage(named: "Back")
self.navigationBar.backIndicatorImage = image
self.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "Back")
self.navigationBar.tintColor = UIColor.blackColor()
But here's result:
As you can see, it should be moved a little down and a little right. I tried to add offset to image this way:
self.navigationBar.backIndicatorImage = image?.imageWithAlignmentRectInsets(UIEdgeInsetsMake(10, 40, 0, 0))
But it does not work, the same. Any ideas?

Although, I feel, there is a scope to move title bit up to match with back button, you can move nav bar button down by:
UINavigationBar.appearance().setTitleVerticalPositionAdjustment(5.0, forBarMetrics: UIBarMetrics.Default)
To move it to right, try adding a flexible space, something like:
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)

Related

Custom UIBarButtonItem added programmatically doesn't respect tintColor

In short, how can I change the color of the black button items (while maintaining control over their size)?
Longer version: I am programmatically adding a number of custom UIBarButtonItems to a UIToolbar. I'm using the solution found here so that I can control the size of the items.
While this fixes the UIBarButtonItem size issue, it does not respect tintColor like a typical UIBarButtonItem would. So I get something like this:
The large white item is the color I want, but not the size. This item was simply added in IB with the tintColor set to default.
The small black items are the size I want, and were added with the following code (N.B. the lines marked with // Not producing intented result):
for e in (self.profile?.expressions)! {
let button = UIButton()
button.setImage(UIImage(named: "emojiph"), for: .normal)
button.addTarget(self, action: #selector(onEmojiInsert), for: .touchUpInside)
let barItem = UIBarButtonItem(customView: button)
barItem.tag = e.family_expression_id
let wConstraint = barItem.customView?.widthAnchor.constraint(equalToConstant: 32)
wConstraint?.isActive = true
let hConstraint = barItem.customView?.heightAnchor.constraint(equalToConstant: 32)
hConstraint?.isActive = true
// Not producing intented result
button.tintColor = UIColor.white
// Not producing intented result
barItem.customView?.tintColor = UIColor.white
// Not producing intented result
barItem.tintColor = UIColor.white
self.emojibar.items?.append(barItem)
// Add flexible spacers
if (e.family_expression_id < (self.profile?.expressions.count)!) {
self.emojibar.items?.append(UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil))
}
}
A workaround would be to provide the white image assets, but I'd prefer to find a more elegant solution if it exists.
To make the button change the color of the presented image to match the tint color then you need to initiate the button as a system type
let button = UIButton(type: .system)

How do I style the backBarButtonItem title in a navigation bar?

I'd like to be able to change only the text color of the back button in the navigation bar.
As a work around, I can sort of do what I'm trying to do by creating a custom view and assigning it to navigationItem.leftBarButtonItem, but it doesn't look very good and I also lose the swipe to pop ability.
Code for the above:
let button = UIButton(type: .system)
let originalImage = #imageLiteral(resourceName: "BackButton")
let scaledImage: UIImage = UIImage(cgImage: originalImage.cgImage!, scale: 30, orientation: originalImage.imageOrientation)
button.setImage(scaledImage, for: .normal)
button.setTitle("YourTitle", for: .normal)
button.sizeToFit()
button.setTitleColor(.brown, for: .normal)
button.tintColor = .blue
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: button)
I also see things suggested like setting attributes of the back button via
navigationController?.navigationBar.topItem.backBarButtonItem?.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.red], for: .normal)
but that doesn't seem to have any effect on the look of the text, despite
print("Attributes: ", navigationController?.navigationBar.topItem?.backBarButtonItem?.titleTextAttributes(for: .normal) ?? "No attributes")
resulting in Attributes: ["NSColor": UIExtendedSRGBColorSpace 1 0 0 1].
I could set tintColor but that would change the color of the back icon in addition to the title.
So what's the best way to do what I want? Is there a way?
Am not sure whether I understood you correctly. But try the below code. This will apply to all the bar button items of your app. Place this code where it is called only once though out app lifecycle. Like application: didFinishLaunchingWithOptions:
let attribs = [NSForegroundColorAttributeName: UIColor.red, NSFontAttributeName: UIFont.boldSystemFont(ofSize: 18)]
UIBarButtonItem.appearance().setTitleTextAttributes(attribs, for: .normal)
I figured it out. You can style the back button by setting self.navigationItem.backBarButtonItem in the previous view controller.
For example, in my case I had TableViewController and when you clicked on a cell, the app would transition to ViewController. In TableViewController I had
public func changeColor() {
let barButton = UIBarButtonItem(title: "Anything", style: .plain, target: nil, action: nil)
barButton.setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.brown], for: .normal)
self.navigationItem.backBarButtonItem = barButton
}
and then in ViewController I had
#IBAction func buttonPressed(_ sender: Any) {
let vc = self.navigationController?.viewControllers[0] as! TableViewController
vc.changeColor()
self.title = "hello very long title asdfasdfasfdasdfasdfasdfasdfasdf"
}
As a result, pressing a button in ViewController would change the color of the title of its back button to brown.

iOS : BackbarButton

Hi I saw too many tutorial from stack overflow for how to change backBarButton I change it but when I check I see my image(custom arrow) beside (default arrow blue one ) I see both beside of each other
I mean the back text changed but the arrow doesn't I see my custom arrow beside default iOS arrow I don't know how should I change it to see my custom arrow only ???
for more detail please check this picture to see this problem
HERE
First You need to hide the default back Button , then supply your Custom one. Following code will help you.
self.navigationItem.hidesBackButton = true
let back: UIButton = UIButton(type: UIButtonType.custom)
back.setImage(UIImage(named: "backarrow"), for: UIControlState.normal)
back.frame = CGRect(x: 0, y: 0, width: 22, height: 22)
back.addTarget(self, action: #selector(self.backPressed), for: UIControlEvents.touchUpInside)
let left: UIBarButtonItem = UIBarButtonItem(customView: back)
self.navigationItem.setLeftBarButton(left, animated: true)
self.navigationController?.navigationBar.topItem?.title = ""
func backPressed() {
//Do your menupulation
}
If I understand you correctly you just need to place your button into Navigation Bar and then set your image name into "image" field.
http://take.ms/Rfrtf - here is for example ;)
Solution 1
You can set default back button color's tint color to red .
UINavigationBar.appearance().tintColor = UIColor.red // add this line appdelegate
Solution 2
self.navigationItem.leftItemsSupplementBackButton = YES;
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: nil, action: nil)
or
self.navigationItem.leftBarButtonItems = #[customBackButtonItem];

setBackButtonBackgroundImage not working

I am simply trying to change the back button icon in the UINavigationBar to a custom image so it matches all the rest of the icons used, however I have approached this two different ways.
One setting the back image an mask image in the UINavigationController within the storyboard inspector to the image, which resulted in the image not being in line with the title or rightBarItem.
Another method I have tried is setBackButtonBackgroundImage within the ViewController file or appDelegate. However the following code;
let backImg: UIImage = UIImage(named: "Back")!
UIBarButtonItem.appearance().setBackButtonBackgroundImage(backImg, forState: .Normal, barMetrics: .Default)
But the result of this was far more weird, the image becomes stretched.
Can anyone help me out on why this is happening or give an alternate method to change the back icon in the UINavigationBar ?
let backImage = UIImage(named: "back_button_name")
UIBarButtonItem.appearance().setBackButtonBackgroundImage(backImage?.resizableImageWithCapInsets(UIEdgeInsetsMake(0, (backImage?.size.width)!-1, 0, 0)), forState: .Normal, barMetrics: .Default)
Swift 3.0
let backImage = UIImage(named: "arrow_left")
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage

Changing navigation bar back button image size globally

Currently I am using the following code to produce a custom back button image for my navbars:
appearance.backIndicatorImage = UIImage(named: "arrow-back")
appearance.backIndicatorTransitionMaskImage = UIImage(named: "arrow-back")
Unfortunately my image is large so it looks better on retina devices, and this method just displays the default size. Any way to shrink it down to get it fitting nicely?
My code will help you
let btnImg = UIImage(named: "Location_OnMap")
let btn = UIBarButtonItem(image: btnImg, style: .Plain, target: self, action: "doSomthing")
self.navigationItem.leftBarButtonItem = btn

Resources