How to change font in textview dynamically with button tap in swift? - 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?

Related

Button subtitle label

One day i did button with title label, subtitle label and image in storyboard and got this effect
Image of button in storyboard
but now when i am trying to do this in code programmly i have a problem, i dont see subtitle..
private var firstPaidPack: UIButton = {
let button = UIButton(type: .custom)
let image = UIImage(systemName: "circle")
button.layer.cornerRadius = 15
button.backgroundColor = UIColor(white: 1, alpha: 0.3)
button.setImage(image, for: .normal)
button.setTitle("1.99$", for: .normal)
button.subtitleLabel?.textAlignment = .center
button.subtitleLabel?.text = "subtitle text to check how it..."
button.titleLabel?.font = UIFont(name: "Arial", size: screenWidth / 375 * 19)
return button
}()
You need to create a UIButton.Configuration and set the subtitle on the configuration object:
var config = UIButton.Configuration.tinted()
config.subtitle = "subtitle text to check how it..."
// Set title and all other properties on the configuration object...
let button = UIButton(type: .custom)
button.configuration = config
You can also set the title and all other properties on the configuration object instead.
Try the below tricks will help you to change the subtitle of the button.
if #available(iOS 15.0, *) {
button.configuration?.subtitle = "Your Subtitle"
}
Have a look here for a detailed answer.

Programmatically added navigation items not displaying

I made a function to display navigation items and bar buttons, however for some reason it doesn't seem to work and it doesn't display anything
override func viewDidLoad() {
configureViewComponents()
}
func configureViewComponents(){
view.backgroundColor = UIColor.init(red: 0/255, green: 0/255, blue: 201/255, alpha: 1)
navigationItem.title = "Login"
navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "arrowshape.turn.up.left"), style: .plain, target: self, action: #selector(handleSignOut))
navigationItem.leftBarButtonItem?.tintColor = .white
If trying to render SFSymbol Icon, use the UIImage(systemName:) initializer:
navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "arrowshape.turn.up.left"), style: .plain, target: self, action: #selector(handleSignOut))
What colour is the background of your navigation bar because you are making the left button item have a tint of white. If your navigation bar is also white I do not believe this will be displayed, as the colours are just the same.
Therefore, I suggest trying to change the tint of the button and see if that makes any difference.

How to add strings with different fonts in UItextField?

I'm trying to add two part of text with different font parameters.
But they always get value from first string.
And there one strange thing, font color is set independently.
let descriptionTextView: UITextView = {
let view = UITextView()
let attributedText = NSMutableAttributedString(string: "Text", attributes:
[.font:UIFont.boldSystemFont(ofSize: 20),
.foregroundColor: UIColor.blue])
attributedText.append(NSAttributedString(string: "\n\n\n Other text", attributes:
[.font: UIFont.italicSystemFont(ofSize: 5),
.foregroundColor: UIColor.gray]))
view.attributedText = attributedText
view.translatesAutoresizingMaskIntoConstraints = false
view.textAlignment = .center
view.font = UIFont.boldSystemFont(ofSize: 20)
view.isEditable = false
view.isScrollEnabled = false
return view
}()
This is how it look in simulator
Remove
view.font = UIFont.boldSystemFont(ofSize: 20)

Font on Back Button on NavBar (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
}
}

UIButton does not change title

I want to change the buttons title on clicking the button:
func dispatchStatusButton(title title:String, backgroundColor:UIColor) {
self.btnDispatchStatus.setTitleWithoutAnimation(title.uppercaseString)
self.btnDispatchStatus.backgroundColor = backgroundColor
self.btnDispatchStatus.kern(2.0)
}
When I call the function:
// Set Button
self.dispatchStatusButton(title: "Inaktiv", backgroundColor: UIColor(red: 40.0/255.0, green: 51.0/255.0, blue: 57.0/255.0, alpha: 1.0))
Nothing happens and I have some feeling my kerning function is the reason, but I don't see why:
extension UIButton {
func setTitleWithoutAnimation(title:String?) {
UIView.setAnimationsEnabled(false)
setTitle(title, forState: .Normal)
layoutIfNeeded()
UIView.setAnimationsEnabled(true)
}
func kern(kerningValue:CGFloat) {
let attributedText = NSAttributedString(string: self.titleLabel!.text!, attributes: [NSKernAttributeName:kerningValue, NSFontAttributeName:self.titleLabel!.font, NSForegroundColorAttributeName:self.titleLabel!.textColor])
self.setAttributedTitle(attributedText, forState: UIControlState.Normal)
}
}
The problem is that self.titleLabel.text property gets updated in the following layout pass. That's why you set the title through setTitle(:forState:) function, and not to the label directly. In your kern function you reference to it when it is still not updated. Try the following:
func kern(kerningValue:CGFloat) {
let title = self.titleForState(.Normal) ?? "" // This gets the new value
let attributedText = NSAttributedString(string: title, attributes: [NSKernAttributeName:kerningValue, NSFontAttributeName:self.titleLabel!.font, NSForegroundColorAttributeName:self.titleLabel!.textColor])
self.setAttributedTitle(attributedText, forState: UIControlState.Normal)
}