Changing Placeholder Text Color with Swift - ios

I have a design that implements a dark blue UITextField, as the placeholder text is by default a dark grey colour I can barely make out what the place holder text says.
I've googled the problem of course but I have yet to come up with a solution while using the Swift language and not Obj-c.
Is there a way to change the placeholder text colour in a UITextField using Swift?

You can set the placeholder text using an attributed string. Just pass the color you want to the attributes parameter.
Swift 5:
let myTextField = UITextField(frame: CGRect(x: 0, y: 0, width: 200, height: 30))
myTextField.backgroundColor = .blue
myTextField.attributedPlaceholder = NSAttributedString(
string: "Placeholder Text",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.white]
)
Swift 3:
myTextField.attributedPlaceholder = NSAttributedString(
string: "Placeholder Text",
attributes: [NSAttributedStringKey.foregroundColor: UIColor.white]
)
Older Swift:
myTextField.attributedPlaceholder = NSAttributedString(
string: "Placeholder Text",
attributes: [NSForegroundColorAttributeName: UIColor.white]
)

You can accomplish this quickly, without adding a line of code, using Interface Builder.
Select the UITextField and open the identity inspector on the right:
Click on the plus button and add a new runtime attribute:
placeholderLabel.textColor (Swift 4)
_placeholderLabel.textColor (Swift 3 or less)
Use Color as type and select the color.
That's it.
You wont see the result until you run your app again.

Create UITextField Extension like this:
extension UITextField{
#IBInspectable var placeHolderColor: UIColor? {
get {
return self.placeHolderColor
}
set {
self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[NSAttributedString.Key.foregroundColor: newValue!])
}
}
}
And in your storyboard or .xib. You will see

In Swift 3.0, Use
let color = UIColor.lightText
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder, attributes: [NSForegroundColorAttributeName : color])
In Siwft 5.0 + Use
let color = UIColor.lightText
let placeholder = textField.placeholder ?? "" //There should be a placeholder set in storyboard or elsewhere string or pass empty
textField.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [NSAttributedString.Key.foregroundColor : color])

This code is working in Swift3:
yourTextFieldName .setValue(UIColor.init(colorLiteralRed: 80/255, green: 80/255, blue: 80/255, alpha: 1.0), forKeyPath: "_placeholderLabel.textColor")
let me know if you have any issue.

To set the placeholder color once for all the UITextField in your app you can do:
UILabel.appearanceWhenContainedInInstancesOfClasses([UITextField.self]).textColor = UIColor.redColor()
This will set the desired color for all TextField placeholders in the entire app. But it is only available since iOS 9.
There is no appearenceWhenContainedIn....() method before iOS 9 in swift but you can use one of the solutions provided here appearanceWhenContainedIn in Swift

In my case, I use Swift 4
I create extension for UITextField
extension UITextField {
func placeholderColor(color: UIColor) {
let attributeString = [
NSAttributedStringKey.foregroundColor: color.withAlphaComponent(0.6),
NSAttributedStringKey.font: self.font!
] as [NSAttributedStringKey : Any]
self.attributedPlaceholder = NSAttributedString(string: self.placeholder!, attributes: attributeString)
}
}
yourField.placeholderColor(color: UIColor.white)

Xcode 9.2 Swift 4
extension UITextField{
#IBInspectable var placeHolderColor: UIColor? {
get {
return self.placeHolderColor
}
set {
self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[NSAttributedStringKey.foregroundColor: newValue!])
}
}
}

For Swift
Create UITextField Extension
extension UITextField{
func setPlaceHolderColor(){
self.attributedPlaceholder = NSAttributedString(string: self.placeholder!, attributes: [NSForegroundColorAttributeName : UIColor.white])
}
}
If Are you set from storyboard.
extension UITextField{
#IBInspectable var placeHolderColor: UIColor? {
get {
return self.placeHolderColor
}
set {
self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[NSAttributedString.Key.foregroundColor : newValue!])
}
}
}

Swift 4 :
txtControl.attributedPlaceholder = NSAttributedString(string: "Placeholder String...",attributes: [NSAttributedStringKey.foregroundColor: UIColor.gray])
Objective-C :
UIColor *color = [UIColor grayColor];
txtControl.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Placeholder String..." attributes:#{NSForegroundColorAttributeName: color}];

Here is my quick implementation for swift 4:
extension UITextField {
func placeholderColor(_ color: UIColor){
var placeholderText = ""
if self.placeholder != nil{
placeholderText = self.placeholder!
}
self.attributedPlaceholder = NSAttributedString(string: placeholderText, attributes: [NSAttributedStringKey.foregroundColor : color])
}
}
use like:
streetTextField?.placeholderColor(AppColor.blueColor)
hope it helps someone!

Swift 3 (probably 2), you can override didSet on placeholder in UITextField subclass to apply attribute on it, this way:
override var placeholder: String? {
didSet {
guard let tmpText = placeholder else {
self.attributedPlaceholder = NSAttributedString(string: "")
return
}
let textRange = NSMakeRange(0, tmpText.characters.count)
let attributedText = NSMutableAttributedString(string: tmpText)
attributedText.addAttribute(NSForegroundColorAttributeName , value:UIColor(white:147.0/255.0, alpha:1.0), range: textRange)
self.attributedPlaceholder = attributedText
}
}

I'm surprised to see how many poor solutions there are here.
Here is a version that will always work.
Swift 4.2
extension UITextField{
#IBInspectable var placeholderColor: UIColor {
get {
return self.attributedPlaceholder?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? UIColor ?? .lightText
}
set {
self.attributedPlaceholder = NSAttributedString(string: self.placeholder ?? "", attributes: [.foregroundColor: newValue])
}
}
}
TIP: If you change the placeholder text after setting the color- the color will reset.

For Swift 3 and 3.1 this works perfectly fine:
passField.attributedPlaceholder = NSAttributedString(string: "password", attributes: [NSForegroundColorAttributeName: UIColor.white])

For Swift 4.0, X-code 9.1 version or iOS 11 you can use following syntax to have different placeholder color
textField.attributedPlaceholder = NSAttributedString(string: "Placeholder Text", attributes: [NSAttributedStringKey.foregroundColor : UIColor.white])

Just write below code into Appdelegate's didFinishLaunchingWithOptions method use this if you want to change in the whole app written in Swift 4.2
UILabel.appearance(whenContainedInInstancesOf: [UITextField.self]).textColor = UIColor.white

Here am i writing all UIDesignable of UITextField. With the help of this code you can directly access it from UI file Inspector in storyboard
#IBDesignable
class CustomTextField: UITextField {
#IBInspectable var leftImage: UIImage? {
didSet {
updateView()
}
}
#IBInspectable var leftPadding: CGFloat = 0 {
didSet {
updateView()
}
}
#IBInspectable var rightImage: UIImage? {
didSet {
updateView()
}
}
#IBInspectable var rightPadding: CGFloat = 0 {
didSet {
updateView()
}
}
private var _isRightViewVisible: Bool = true
var isRightViewVisible: Bool {
get {
return _isRightViewVisible
}
set {
_isRightViewVisible = newValue
updateView()
}
}
func updateView() {
setLeftImage()
setRightImage()
// Placeholder text color
attributedPlaceholder = NSAttributedString(string: placeholder != nil ? placeholder! : "", attributes:[NSAttributedString.Key.foregroundColor: tintColor])
}
func setLeftImage() {
leftViewMode = UITextField.ViewMode.always
var view: UIView
if let image = leftImage {
let imageView = UIImageView(frame: CGRect(x: leftPadding, y: 0, width: 20, height: 20))
imageView.image = image
// Note: In order for your image to use the tint color, you have to select the image in the Assets.xcassets and change the "Render As" property to "Template Image".
imageView.tintColor = tintColor
var width = imageView.frame.width + leftPadding
if borderStyle == UITextField.BorderStyle.none || borderStyle == UITextField.BorderStyle.line {
width += 5
}
view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: 20))
view.addSubview(imageView)
} else {
view = UIView(frame: CGRect(x: 0, y: 0, width: leftPadding, height: 20))
}
leftView = view
}
func setRightImage() {
rightViewMode = UITextField.ViewMode.always
var view: UIView
if let image = rightImage, isRightViewVisible {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
imageView.image = image
// Note: In order for your image to use the tint color, you have to select the image in the Assets.xcassets and change the "Render As" property to "Template Image".
imageView.tintColor = tintColor
var width = imageView.frame.width + rightPadding
if borderStyle == UITextField.BorderStyle.none || borderStyle == UITextField.BorderStyle.line {
width += 5
}
view = UIView(frame: CGRect(x: 0, y: 0, width: width, height: 20))
view.addSubview(imageView)
} else {
view = UIView(frame: CGRect(x: 0, y: 0, width: rightPadding, height: 20))
}
rightView = view
}
#IBInspectable public var borderColor: UIColor = UIColor.clear {
didSet {
layer.borderColor = borderColor.cgColor
}
}
#IBInspectable public var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable public var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
#IBInspectable public var bottomBorder: CGFloat = 0 {
didSet {
borderStyle = .none
layer.backgroundColor = UIColor.white.cgColor
layer.masksToBounds = false
// layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
layer.shadowOpacity = 1.0
layer.shadowRadius = 0.0
}
}
#IBInspectable public var bottomBorderColor : UIColor = UIColor.clear {
didSet {
layer.shadowColor = bottomBorderColor.cgColor
layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
layer.shadowOpacity = 1.0
layer.shadowRadius = 0.0
}
}
/// Sets the placeholder color
#IBInspectable var placeHolderColor: UIColor? {
get {
return self.placeHolderColor
}
set {
self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ? self.placeholder! : "", attributes:[NSAttributedString.Key.foregroundColor: newValue!])
}
}
}

Use like this in Swift,
let placeHolderText = textField.placeholder ?? ""
let str = NSAttributedString(string:placeHolderText!, attributes: [NSAttributedString.Key.foregroundColor :UIColor.lightGray])
textField.attributedPlaceholder = str
In Objective C
NSString *placeHolder = [textField.placeholder length]>0 ? textField.placeholder: #"";
NSAttributedString *str = [[NSAttributedString alloc] initWithString:placeHolder attributes:#{ NSForegroundColorAttributeName : [UIColor lightGrayColor] }];
textField.attributedPlaceholder = str;

In my case, I had to make the placeholder into black color. The name of my UITextField is passwordText. Below code is tested in Swift 5 and is working fine for me. I also had an existing text for the corresponding placeholder.
let placeholderColor = UIColor.black
passwordText.attributedPlaceholder = NSAttributedString(string: passwordText.placeholder!, attributes: [NSAttributedString.Key.foregroundColor : placeholderColor])

crubio's answer update for Swift 4
Select the UITextField and open the identity inspector on the right:
Click on the plus button and add a new runtime attribute: placeholderLabel.textColor (instead of _placeholderLabel.textColor)
Use Color as type and select the color.
If you run your project, you will see the changes.

For swift 4.2 and above you can do it as below:
textField.attributedPlaceholder = NSAttributedString(string: "Placeholder Text", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])

In my case, I have done following:
extension UITextField {
#IBInspectable var placeHolderColor: UIColor? {
get {
if let color = self.attributedPlaceholder?.attribute(.foregroundColor, at: 0, effectiveRange: nil) as? UIColor {
return color
}
return nil
}
set (setOptionalColor) {
if let setColor = setOptionalColor {
let string = self.placeholder ?? ""
self.attributedPlaceholder = NSAttributedString(string: string , attributes:[NSAttributedString.Key.foregroundColor: setColor])
}
}
}
}

extension UITextField{
#IBInspectable var placeHolderColor: UIColor? {
get {
return self.placeHolderColor
}
set {
self.attributedPlaceholder = NSAttributedString(string:self.placeholder != nil ?
self.placeholder! : "",
attributes:[NSAttributedString.Key.foregroundColor : newValue!])
}
}
}

For Swift
func setPlaceholderColor(textField: UITextField, placeholderText: String) {
textField.attributedPlaceholder = NSAttributedString(string: placeholderText, attributes: [NSForegroundColorAttributeName: UIColor.pelorBlack])
}
You can use this;
self.setPlaceholderColor(textField: self.emailTextField, placeholderText: "E-Mail/Username")

It is more about personalize your textField but anyways I'll share this code got from another page and made it a little better:
import UIKit
extension UITextField {
func setBottomLine(borderColor: UIColor, fontColor: UIColor, placeHolderColor:UIColor, placeHolder: String) {
self.borderStyle = UITextBorderStyle.none
self.backgroundColor = UIColor.clear
let borderLine = UIView()
let height = 1.0
borderLine.frame = CGRect(x: 0, y: Double(self.frame.height) - height, width: Double(self.frame.width), height: height)
self.textColor = fontColor
borderLine.backgroundColor = borderColor
self.addSubview(borderLine)
self.attributedPlaceholder = NSAttributedString(
string: placeHolder,
attributes: [NSAttributedStringKey.foregroundColor: placeHolderColor]
)
}
}
And you can use it like this:
self.textField.setBottomLine(borderColor: lineColor, fontColor: fontColor, placeHolderColor: placeHolderColor, placeHolder: placeHolder)
Knowing that you have an UITextField connected to a ViewController.
Source: http://codepany.com/blog/swift-3-custom-uitextfield-with-single-line-input/

For Objective C:
UIColor *color = [UIColor colorWithRed:0.44 green:0.44 blue:0.44 alpha:1.0];
emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"Friend's Email" attributes:#{NSForegroundColorAttributeName: color}];
For Swift:
emailTextField.attributedPlaceholder = NSAttributedString(string: "Friend's Email",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])

Objective C code for changing placeholder text color.
First import this objc/runtime class -
#import <objc/runtime.h>
then replace your textfield name -
Ivar ivar = class_getInstanceVariable([UITextField class], "_placeholderLabel");
UILabel *placeholderLabel = object_getIvar(YourTxtField, ivar);
placeholderLabel.textColor = [UIColor whiteColor];

for iOS13
+(void)ChangeplaceholderColor :(UITextField *)TxtFld andColor:(UIColor*)color {
NSMutableAttributedString *placeholderAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:TxtFld.attributedPlaceholder];
[placeholderAttributedString addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, [placeholderAttributedString length])];
TxtFld.attributedPlaceholder = placeholderAttributedString;
}

Use this for adding an attributed placeholder:
let attributes : [String : Any] = [ NSForegroundColorAttributeName: UIColor.lightGray,
NSFontAttributeName : UIFont(name: "Helvetica Neue Light Italic", size: 12.0)!
]
x_textfield.attributedPlaceholder = NSAttributedString(string: "Placeholder Text", attributes:attributes)

For Swift 4
txtField1.attributedPlaceholder = NSAttributedString(string: "-", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])

Related

Search Bar textfield cursor color not changing in mac Catalyst it's showing black color ios swift

i also try to change with "searchController.searchBar.searchTextField.tintColor = .white"
but it's not working issue facing after xcode 13 update.
Try to create a custom searchController and into the setup to change the tintColor of all the subviews that are different of UIButton .
Here an example :
class CustomSearchController: UISearchController {
var placeHolder:String?
private var catalogSearchBar = CatalogSearchBar()
override public var searchBar: UISearchBar {
get {
catalogSearchBar.placeholder = placeHolder
return catalogSearchBar
}
}
}
class CatalogSearchBar: UISearchBar {
init() {
super.init(frame: .zero)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
override func layoutSubviews() {
super.layoutSubviews()
setup()
}
private func setup() {
backgroundColor = Constants.shared.navigationBar.lightModeBgColor
// text field
let textField = searchTextField
textField.subviews.forEach { (view) in
if ((view as? UIButton) != nil) {
view.tintColor = UIColor.white
}
}
textField.frame.size.height = 35
self.searchTextPositionAdjustment = UIOffset(horizontal: 4, vertical: 0)
textField.layer.cornerRadius = 15
textField.placeholder = self.placeholder
textField.attributedPlaceholder = NSAttributedString(string: self.placeholder != nil ? self.placeholder! : "", attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
textField.layer.masksToBounds = true
textField.layer.backgroundColor = UIColor.white.withAlphaComponent(0.25).cgColor
if let view = textField.value(forKey: "backgroundView") as? UIView {
view.removeFromSuperview()
}
textField.font = UIFont(name: "Montserrat-Regular", size: 15)
textField.textColor = UIColor.white
textField.tintColor = UIColor.white
// search icon
let leftView: UIView = {
let image = UIImage(named: "search")
let padding = 8
let size = 20
let outerView = UIView(frame: CGRect(x: 0, y: 0, width: size + padding, height: size) )
let iconView = UIImageView(frame: CGRect(x: padding, y: 0, width: size, height: size))
iconView.tintColor = UIColor.white
iconView.image = image
outerView.addSubview(iconView)
return outerView
}()
textField.leftView = leftView
}
}

swift i want to change search bar background colour white with black border

here the screenshot that I want output please check
I want the result like this search bar with background color white and black border
here my code is
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
for subView in searchBar.subviews {
if !subView.subviews.contains(where: { $0 as? UITextField != nil }) { continue }
guard let textField = subView.subviews.first(where: { $0 as? UITextField != nil }) as? UITextField else { return }
let placeholder = NSMutableAttributedString(
string: "Search",
attributes: [.font: UIFont(name: "Helvetica", size: 15.0)!,
.foregroundColor: UIColor.gray
])
textField.attributedPlaceholder = placeholder
textField.layer.cornerRadius = textField.frame.size.height / 2
textField.layer.masksToBounds = true
textField.textColor = .black
textField.backgroundColor = .white
}
this is my output screenshot please check it
I am unable to set search bar, please suggest me
Good day! If I understand you correctly, then this may solve your problem. Extension for UISearchBar (Swift 5):
import UIKit
extension UISearchBar {
func setupSearchBar(background: UIColor = .white, inputText: UIColor = .black, placeholderText: UIColor = .gray, image: UIColor = .black) {
self.searchBarStyle = .minimal
self.barStyle = .default
// IOS 12 and lower:
for view in self.subviews {
for subview in view.subviews {
if subview is UITextField {
if let textField: UITextField = subview as? UITextField {
// Background Color
textField.backgroundColor = background
// Text Color
textField.textColor = inputText
// Placeholder Color
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])
// Default Image Color
if let leftView = textField.leftView as? UIImageView {
leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
leftView.tintColor = image
}
let backgroundView = textField.subviews.first
backgroundView?.backgroundColor = background
backgroundView?.layer.cornerRadius = 10.5
backgroundView?.layer.masksToBounds = true
}
}
}
}
// IOS 13 only:
if let textField = self.value(forKey: "searchField") as? UITextField {
// Background Color
textField.backgroundColor = background
// Text Color
textField.textColor = inputText
// Placeholder Color
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", attributes: [NSAttributedString.Key.foregroundColor : placeholderText])
// Default Image Color
if let leftView = textField.leftView as? UIImageView {
leftView.image = leftView.image?.withRenderingMode(.alwaysTemplate)
leftView.tintColor = image
}
}
}
}
Also, you can try to do it with an image.
The way to do this only using Apple APIs is to create an image and use setSearchFieldBackgroundImage:
self.searchBar.setSearchFieldBackgroundImage(UIImage(named: "SearchFieldBackground"), for: UIControlState.normal)
Source: Cannot change search bar background color

Swift - UITextView text is getting cut when applying custom font

I am using UITextView inside super view UIView to display text with many different types of fonts.
But UITextView text is getting cut when applying specific font Smoothie_Life_Swirls_2.0
I am creating textView programmatically as below,
textView = ResizableTextView(frame: CGRect(x: 0, y: 0, width: contentView.frame.size.width, height: contentView.frame.size.height))
textView.isScrollEnabled = false
textView.alignment = .center
textView.backgroundColor = UIColor.clear
textView.fontName = "Helveticas"
textView.fontSize = contentView.frame.size.height
textView.textColor = textColor
textView.autoresizingMask = [.flexibleTopMargin, .flexibleRightMargin, .flexibleBottomMargin, .flexibleLeftMargin, .flexibleWidth, .flexibleHeight]
textView.delegate = self
contentView.addSubview(textView)
textView.becomeFirstResponder()
Here ResizableTextView is my UITextView class, in which fontName and fontSize will be set
public class ResizableTextView: UITextView {
public private(set) var textAttributes: [String: AnyObject] = [:]
public var fontName: String = "Helvetica" {
didSet {
let font = UIFont(name: fontName, size: fontSize)
textAttributes[NSFontAttributeName] = font
self.attributedText = NSAttributedString(string: self.text, attributes: textAttributes)
self.font = font
}
}
public var fontSize: CGFloat = 20 {
didSet {
let font = UIFont(name: fontName, size: fontSize)
textAttributes[NSFontAttributeName] = font
self.attributedText = NSAttributedString(string: self.text, attributes: textAttributes)
self.font = font
}
}
}
When I set Smoothie_Life_Swirls_2.0 font to textView using ResizableTextView's fontName property, at that time text is getting cut.
Text1 - Getting Output
Text2 - Required Output
I want to fit the text in UITextView same as Text2, but I am getting the result as displayed in Text1.

My navigation bar's large title is too wide. How to fix that?

I am using navigation controller, and I've set to true its navigation bar's prefersLargeTitle property. Everything works fine, but when the text of my title becomes too big, it doesn't fit in space. Here how it looks:
Is it possible to somehow make the title (while the navigation bar's prefersLargeTitle property is set to true) dynamically adjust its font size, and if it is so, how to achieve that?
This is the workaround that I found
override func viewDidLoad() {
super.viewDidLoad()
title = yourTitle
adjustLargeTitleSize()
}
extension UIViewController {
func adjustLargeTitleSize() {
guard let title = title, #available(iOS 11.0, *) else { return }
let maxWidth = UIScreen.main.bounds.size.width - 60
var fontSize = UIFont.preferredFont(forTextStyle: .largeTitle).pointSize
var width = title.size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: fontSize)]).width
while width > maxWidth {
fontSize -= 1
width = title.size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: fontSize)]).width
}
navigationController?.navigationBar.largeTitleTextAttributes =
[NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: fontSize)
]
}
}
All you need is:
UILabel.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).adjustsFontSizeToFitWidth = true
Working also with SwiftUI on iOS 15.
This question is somewhat answered here: How to resize Title in a navigation bar dynamically.
self.title = "Your TiTle Text"
let tlabel = UILabel(frame: CGRectMake(0, 0, 200, 40))
tlabel.text = self.title
tlabel.textColor = UIColor.whiteColor()
tlabel.font = UIFont(name: "Helvetica-Bold", size: 30.0)
tlabel.backgroundColor = UIColor.clearColor()
tlabel.adjustsFontSizeToFitWidth = true
self.navigationItem.titleView = tlabel
That being said, this is slightly different, in that you have the prefersLargeTitle property set.
Now, I am not sure whether the tlabel.adjustsFontSizeToFitWidth = true overrides the prefersLargeTitle property, but try it out and see if it works. There is also some additional information regarding navigation item large titles here: https://developer.apple.com/documentation/uikit/uinavigationitem/2909056-largetitledisplaymode. Hope this helps.
Tested for iOS12 ~ iOS14
extension UINavigationController {
func adjustFontSize(with title: String) {
let insetToEdge: CGFloat = 16
let maxWidth = navigationBar.bounds.width - insetToEdge - insetToEdge
let largeTitleFont = UIFont.preferredFont(forTextStyle: .largeTitle)
var fontSize = largeTitleFont.pointSize
var largeTitleTextAttributes: [NSAttributedString.Key: Any] = [:]
var largeTitleSize: CGSize
if #available(iOS 13.0, *) {
largeTitleSize = NSAttributedString(
string: title,
attributes: navigationBar.standardAppearance.largeTitleTextAttributes)
.size()
} else {
largeTitleTextAttributes = [NSAttributedString.Key.font: largeTitleFont]
largeTitleSize = NSAttributedString(
string: title,
attributes: largeTitleTextAttributes)
.size()
}
guard largeTitleSize.width > maxWidth else { return }
while largeTitleSize.width > maxWidth {
fontSize -= 1
if #available(iOS 13.0, *) {
largeTitleTextAttributes = navigationBar.standardAppearance.largeTitleTextAttributes
}
largeTitleTextAttributes[NSAttributedString.Key.font] = UIFont.BO.font(
ofSize: fontSize,
weight: .semiBold)
largeTitleSize = NSAttributedString(
string: title,
attributes: largeTitleTextAttributes)
.size()
}
if #available(iOS 13.0, *) {
navigationBar.standardAppearance.largeTitleTextAttributes = largeTitleTextAttributes
} else {
navigationBar.largeTitleTextAttributes = largeTitleTextAttributes
}
}
}
call from viewDidLoad()
Made an edit to #vicente.fava answer - this works great.
self.title = longTitle
self.navigationController?.navigationBar.prefersLargeTitles = true
adjustLargeTitleSize()
extension UIViewController {
func adjustLargeTitleSize() {
guard let title = title, #available(iOS 11.0, *) else { return }
let maxWidth = UIScreen.main.bounds.size.width - 60
var fontSize = UIFont.preferredFont(forTextStyle: .largeTitle).pointSize
var width = title.size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)]).width
while width > maxWidth {
fontSize -= 1
width = title.size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)]).width
}
navigationController?.navigationBar.largeTitleTextAttributes =
[NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: fontSize)
]
}
}

Subclassing UIViewController With NavigationBar Title

I'm trying to subclass a UIViewController with a label (UILabel) set to the title of the navigation bar. Instead of setting a name to self.title, I want to use an attributed string to set the title.
class BasicViewController: UIViewController {
var titleString = ""
func setup() {
//self.title = titleString
let navBar = navigationController!.navigationBar
navBar.barTintColor = UIColor.redColor()
let atext = NSMutableAttributedString(string: titleString)
atext.addAttribute(NSForegroundColorAttributeName, value: UIColor.whiteColor(), range: NSMakeRange(0, atext.length))
atext.addAttribute(NSStrokeColorAttributeName, value: UIColor.yellowColor(), range: NSMakeRange(0, atext.length))
atext.addAttribute(NSStrokeWidthAttributeName, value: NSNumber.init(float: -1.0), range: NSMakeRange(0, atext.length))
let titleLabel:UILabel = UILabel.init(frame: CGRectMake(50, 3, 220, 44))
titleLabel.attributedText = atext
titleLabel.textAlignment = NSTextAlignment.Center
titleLabel.font = UIFont(name: "Helvetica", size: 24.0)
}
}
class HomeViewController: BasicViewController {
override func viewDidLoad() {
super.viewDidLoad()
titleString = "My App"
setup()
}
}
If I run this code, I get an empty title. What am I doing wrong? Thanks.
I don't see where you're setting self.navigationItem.titleView = titleLabel

Resources