Font on Back Button on NavBar (Swift) - swift

I can adjust all the other aspects of the appearance of my navigation bar - but the font of 'Back' remains stubborn.
The MWE below shows four things I have tried to no avail
1)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedString.Key.font: UIFont(name: "Helvetica-Bold", size: 4)!], for: .normal)
return true
}
2) 3) 4)
class customNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
UIBarButtonItem.appearance().setTitleTextAttributes(
[
NSAttributedString.Key.font : UIFont(name: "Rockwell", size: 4)!,
NSAttributedString.Key.foregroundColor : UIColor.white,
], for: .normal )
navigationItem.backBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.font: UIFont(name: "Chalkduster", size: 7)!], for: .normal)
navigationBar.topItem?.backBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.font: UIFont(name: "AvenirNextCondensed-DemiBoldItalic", size: 4)!], for: .normal)
}
}

It's simplest in iOS 13:
let app = UINavigationBarAppearance()
app.backButtonAppearance.normal.titleTextAttributes = [
// whatever
]
UINavigationBar.appearance().standardAppearance = app
Before iOS 13, the API doesn't draw the distinction you want to draw. You just have to set the individual bar button item title text attributes for all your back buttons one at a time.
let title = // ...
let back = UIBarButtonItem(title: title, style: .plain, target: nil, action: nil)
back.setTitleTextAttributes([
// whatever
], for: .normal)
self.navigationItem.backBarButtonItem = back
(Remember also that your back bar button item is not the back bar button item when this view controller is visible, but when another view controller is pushed on top of this one.)

This solution seems to work well for me:
// Set all fonts in the navigation controller
class CustomNavigationController: UINavigationController {
// Font names
let normalFontName = "AppleSDGothicNeo-Medium"
let boldFontName = "AppleSDGothicNeo-Bold"
// Font size
let fontSize = CGFloat(13)
// Create fonts
let backButtonFont = UIFont(name: normalFontName, size: fontSize)
let titleFont = UIFont(name: boldFontName, size: fontSize)
override func viewDidLoad() {
super.viewDidLoad()
// Set standard appearance
let appearance = UINavigationBarAppearance()
appearance.backButtonAppearance.normal.titleTextAttributes = [NSAttributedString.Key.font: backButtonFont]
appearance.titleTextAttributes = [NSAttributedString.Key.font: titleFont]
UINavigationBar.appearance().standardAppearance = appearance
}
}

Related

Navigation bar title will not show (color for title will not work)

All the code looks fine, but the result is just a green navigation bar with no title showing, even though the title should show in white.
func configureUI() {
view.backgroundColor = .white
//configure NavBar
navigationController?.navigationItem.title = "Add Personal Finance Log"
navigationController?.navigationBar.isHidden = false
navigationController?.navigationItem.hidesBackButton = true
let backButton = UIBarButtonItem(image: UIImage(systemName: "chevron.left")?.withTintColor(.white, renderingMode: .alwaysOriginal), style: .plain, target: self, action: #selector(handleBack))
navigationItem.leftBarButtonItem = backButton
let appearance = UINavigationBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.backgroundColor = hexStringToUIColor(hex: APP_HEXCOLOR_MAIN)
let titleAttribute = [NSAttributedString.Key.font: UIFont.init(name: APP_FONT_MAIN, size: 22), NSAttributedString.Key.foregroundColor: UIColor.white]
appearance.titleTextAttributes = titleAttribute as [NSAttributedString.Key : Any]
navigationItem.standardAppearance = appearance
navigationItem.scrollEdgeAppearance = appearance
navigationItem.compactAppearance = appearance
}
Replace this line:
navigationController?.navigationItem.title = "Add Personal Finance Log"
With:
title = "Add Personal Finance Log"
Add this for change color (for example to red):
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red]
In case you want large title add this:
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red]
The code doesn't "look fine" at all. You have no business talking to the navigationController?.navigationItem. That does nothing. If you are a view controller, you talk to your navigationItem.

UINavigation custom back button image not working in iOS 15

I want to apply UINavigation custom background image and back button image also for iOS 14 everything is working fine but as I try to run the app on iOS 15 back button image not working instead it's showing the default back button which I want to replace with custom back button image I am using below code
if #available(iOS 15.0, *) {
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground()
appearance.backgroundImage = image
appearance.setBackIndicatorImage(backButtonImage, transitionMaskImage: backButtonImage)
if Locale.current.languageCode == "fr" {
appearance.titleTextAttributes = [ NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor(hexString: "#231F20")]
} else {
appearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor(hexString: "#231F20")]
}
navigationItem.standardAppearance = appearance
navigationItem.scrollEdgeAppearance = appearance
} else {
self.navigationController?.navigationBar.setBackgroundImage(image, for: .default)
self.navigationController?.navigationBar.backIndicatorImage = backButtonImage
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = backButtonImage
if Locale.current.languageCode == "fr" {
self.navigationController?.navigationBar.titleTextAttributes = [ NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14), NSAttributedString.Key.foregroundColor: UIColor(hexString: "#231F20")]
} else {
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor(hexString: "#231F20")]
}
}
Sharing with you a common function I have made in a BaseViewController which is the superclass of all my View Controllers.
I Simply call the addBackButton function from viewDidLoad from any of the VC I want to add the back button.
It also handles the back navigation automatically. (takes care if you have presented or pushed a vc)
func addBackButton(tint : UIColor? = nil, backImage : UIImage? = Constants.Images.kImageForBackNavigation){
let buttonForBack = UIButton(type: .custom)
var tintColorForImage = UIColor.white
if tint != nil {
tintColorForImage = tint!
}
let image = backImage!.withRenderingMode(.alwaysTemplate)
buttonForBack.setImage(image, for: .normal)
buttonForBack.imageView?.tintColor = tintColorForImage
buttonForBack.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
buttonForBack.addTarget(self, action: #selector(BaseViewController.closeViewController), for: .touchUpInside)
let barButtonItemForClose = UIBarButtonItem(customView: buttonForBack)
self.navigationItem.setLeftBarButton(barButtonItemForClose, animated: false)
}
#objc func closeViewController(){
if self == self.navigationController?.children.first {
DispatchQueue.main.async {
self.navigationController?.dismiss(animated: true, completion: nil);
}
}
else{
DispatchQueue.main.async {
self.navigationController?.popViewController(animated: true)
}
}
}

Is it possible to have only large titles in the navigation bar?

I want my application to have large titles, however, when the user scrolls, I don't want the regular/normal navigation bar to appear. I just want the large bar to scroll up along with the tableview. Is this possible without making custom views in the navigation bar? I have done it successfully with custom views, but it isn't as fluid and putting a UISearchController inside is a pain.
func createNavController(vc: UIViewController, title: String, image: UIImage, tag: Int) -> UINavigationController {
let navController = UINavigationController(rootViewController: vc)
navController.navigationBar.prefersLargeTitles = true
navController.navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navController.navigationBar.shadowImage = UIImage()
navController.navigationBar.tintColor = .headerColor
navController.tabBarItem = UITabBarItem(title: title, image: image.withRenderingMode(.alwaysTemplate), tag: tag)
navController.navigationBar.topItem?.title = title
navController.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.headerColor, .font: UIFont.customHeaderFont(size: 25)]
navController.navigationBar.largeTitleTextAttributes = [.foregroundColor: UIColor.headerColor, .font: UIFont.customHeaderFont(size: 40)]
// let titleLabel = UILabel()
// titleLabel.text = title
// titleLabel.textColor = .headerColor
// titleLabel.font = UIFont.customHeaderFont(size: navController.navigationBar.frame.height - 5)
// navController.navigationBar.addSubview(titleLabel)
// titleLabel.anchor(top: nil, left: navController.navigationBar.leftAnchor, bottom: nil, right: nil, paddingTop: 0, paddingLeft: 20, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
// titleLabel.centerYAnchor.constraint(equalTo: navController.navigationBar.centerYAnchor).isActive = true
return navController
}
Use my extension iOS 13 Swift 5 tested
extension UIViewController {
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
if #available(iOS 13.0, *) {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.backgroundColor = backgoundColor
navigationController?.navigationBar.standardAppearance = navBarAppearance
navigationController?.navigationBar.compactAppearance = navBarAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
navigationController?.navigationBar.isTranslucent = false
navigationController?.navigationBar.tintColor = tintColor
navigationItem.title = title
} else {
// Fallback on earlier versions
navigationController?.navigationBar.barTintColor = backgoundColor
navigationController?.navigationBar.tintColor = tintColor
navigationController?.navigationBar.isTranslucent = false
navigationItem.title = title
}
}}
How to use:
configureNavigationBar(largeTitleColor: .yourColor, backgoundColor: .yourColor, tintColor: .yourColor, title: "yuorTitle", preferredLargeTitle: true)
Set ViewController-based status bar...... to NO in info.plist if you want light Content
If you don't want largeTitles set it to false
for tranlsucent change navBarAppearance.configureWithOpaqueBackground() in:
navBarAppearance.configureWithDefaultBackground()
navigationController?.navigationBar.isTranslucent = true
in the call set background color to .clear
UPDATE: If you want to start with navigation controller and large Titles at first controller, don't forget to set launch controller in Scene Delegate like this:
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
window?.makeKeyAndVisible()
let vC = UINavigationController(rootViewController: YourFirstViewController())
window?.rootViewController = vC
hope this help :)
You can probe create your custom navigation controller and called in your view controllers; is more easy, customize the native navigation controller is hard, but you can do it scouring subviews in the natives elements.

How to change font in textview dynamically with button tap in swift?

I created a textview like below and I add keyboard button for users can change the font. It is working but it changes whole text's font but I want to change fonts only after button clicking. Can you help about ?
func setKeyboard() { // this is for keyboard button
let bar = UIToolbar()
let flex = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: self, action: nil)
let font = UIBarButtonItem(image: UIImage(named: "icons8-image-80"), style: .plain, target: self, action: #selector(fontTapped))
bar.barTintColor = UIColor(displayP3Red: 30/255, green: 30/255, blue: 30/255, alpha: 1)
bar.sizeToFit()
writePost.inputAccessoryView = bar
}
// and this one is fontTapped function
#objc func fontTapped() {
if fontTag == 0 {
let attributedText = NSMutableAttributedString(string: writePost.text, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12)])
writePost.attributedText = attributedText
fontTag = 1
} else {
writePost.font = UIFont(name: "AvenirNext-DemiBoldItalic", size: 16)
fontTag = 0
}
}
To change the font / style for what the user types from now on, change the typingAttributes of the text view.
https://developer.apple.com/documentation/uikit/uitextview/1618629-typingattributes
You will be using the attributedText property of the UITextField like so:
https://medium.com/swift-india/multiple-font-style-for-uilable-text-using-nsattributed-string-3f121036a533
And probably build your attributed string in shouldChangeCharactersInRange() of the UITextFieldDelegate, in order to change the font of the incoming characters.
How shouldChangeCharactersInRange works in Swift?

How to remove title from UIBarButtonItem.appearance() on iOS 10.3

I want to personalize the Back Button of my app to have a consistent looking. So I'm setting a image as the Back Button of a Navigation Bar.
The code bellow works fine on any iOS above iOS 10. So, I'm trying to make it work on iOS 10.3.1.
This is basically all the code, that I'm setting on AppDelegate didFinishLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
applyNavigationAppearances()
return true
}
private func applyNavigationAppearances() {
let navigationAppearance = UINavigationBar.appearance()
navigationAppearance.barTintColor = .white
navigationAppearance.barStyle = .black
navigationAppearance.backIndicatorImage = UIImage()
navigationAppearance.backIndicatorTransitionMaskImage = UIImage()
navigationAppearance.tintColor = .gray
navigationAppearance.titleTextAttributes = [
NSAttributedString.Key.foregroundColor: UIColor.gray,
NSAttributedString.Key.font: UIFont(name: "Helvetica-Bold", size: 20)
]
let backImage = UIImage(named: "chevron-orange-left")
let backImageUIEdgeInsets = UIEdgeInsets(top: -4, left: -8, bottom: -2, right: 8)
let backImageWithAlignmentRectInsets = backImage?.withAlignmentRectInsets(backImageUIEdgeInsets)
let barButtonAppearance = UIBarButtonItem.appearance()
barButtonAppearance.setBackButtonBackgroundVerticalPositionAdjustment(-1.0, for: .default)
barButtonAppearance.setBackButtonBackgroundImage(backImageWithAlignmentRectInsets, for: .normal, barMetrics: .default)
}
This is what I want and get on any iOS above 10:
This is what I get on iOS 10.3.1:
Edit 1: It's worth saying this is a big app. A solution that didn't involved changing every ViewController would be ideal.
Edit 2: Thank you for answer guys. However, all solutions posted here are distorting the image shorter or longer, so they don't quite solve my problem.
You have:
let backImage = UIImage(named: "icon")
let backImageUIEdgeInsets = UIEdgeInsets(top: -4, left: -8, bottom: -2, right: 8)
let backImageWithAlignmentRectInsets = backImage?.withAlignmentRectInsets(backImageUIEdgeInsets)
appearance.setBackButtonBackgroundVerticalPositionAdjustment(-1.0, for: .default)
appearance.setBackButtonBackgroundImage(backImageWithAlignmentRectInsets,
for: .normal,
barMetrics: .default)
After that you can add :
appearance.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear],
for: .normal)
appearance.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear],
for: .highlighted)
I check this on iPhone 7 10.3.1