Swift UITextView with different formatting - swift

Sorry for a basic question, but I'm not sure where to start. Is the following possible in Swift?
In a UITextView (Not a label, as in the possible duplicate), different bits of text having different formatting: for instance, a line of large text in the same UITextView as a line of small text. Here is a mockup of what I mean:
Is this possible in one UITextView?

You should have a look at NSAttributedString. Here's an example of how you could use it:
let largeTextString = "Here is some large, bold text"
let smallTextString = "Here is some smaller text"
let textString = "\n\(largeTextString)\n\n\(smallTextString)"
let attrText = NSMutableAttributedString(string: textString)
let largeFont = UIFont(name: "Arial-BoldMT", size: 50.0)!
let smallFont = UIFont(name: "Arial", size: 30.0)!
// Convert textString to NSString because attrText.addAttribute takes an NSRange.
let largeTextRange = (textString as NSString).range(of: largeTextString)
let smallTextRange = (textString as NSString).range(of: smallTextString)
attrText.addAttribute(NSFontAttributeName, value: largeFont, range: largeTextRange)
attrText.addAttribute(NSFontAttributeName, value: smallFont, range: smallTextRange)
textView.attributedText = attrText
The result:

Related

Remove HTML elements from NSAttributedString

let string = "To find out more, click <span>here</span> to go to our help page"
let attributedString = NSAttributedString(string: string)
uitextview.attributedText = attributedString
Now the string constant is dynamically created so I can't manipulate it's content directly. And I'm displaying the attributedString in a UITextView and after the user made some changes, I want to edit the attributedString and remove the a tag from the attributedString
I want to remove the a tag and it's HTML contents except it's text. And I can't do something like this:
attributedString.string
Because there are other HTML elements that might be in the attributedString which might loose it's attributes
What I have done so far:
let range = NSRange(location: 12, length: 14)
let attributedText = uitextview.attributedText!
let subAttrText = attributedText.attributedSubstring(from: range) // "more, click he"
let subText = subAttrText.string
let mutableString = NSMutableAttributedString(attributedString: attributedText)
mutableString.replaceCharacters(in: range, with: subText)
uitextview.attributedText = mutableString
Expectation: To find out re to go to our help page
Result: To find out <span>re</span> to go to our help page
How can I make the link text to be converted to just plain text?
So I found a way to figure it out
let range = NSRange(location: 12, length: 14)
let attributedText = uitextview.attributedText!
let subAttrText = attributedText.attributedSubstring(from: range) // "more, click he"
let subText = subAttrText.string
let mutableString = NSMutableAttributedString(attributedString: attributedText)
mutableString.deleteCharacters(in: range)
mutableString.insert(subText, at: range.location)
uitextview.attributedText = mutableString

Multiline multicolor attributed text in swift

How can I build something like this using attributed text? I tried adding line feed (\n), it didn't work, just displayed first line and cropped next two, removing \n will display two parts in single line:
let mutableAttributedString = NSMutableAttributedString()
let regularAttribute = [NSAttributedStringKey.font: UIFont(name: "Avenir-Light", size: 45.0), NSAttributedStringKey.foregroundColor: UIColor.yellow]
let boldAttribute = [NSAttributedStringKey.font: UIFont(name: "Avenir-Light", size: 25.0), NSAttributedStringKey.foregroundColor: UIColor.white]
let mutableAttributedString2 = NSMutableAttributedString()
let boldAttributedString = NSAttributedString(string: "person", attributes: boldAttribute)
let regularAttributedString = NSAttributedString(string: "\(self.requestCount)", attributes: regularAttribute)
mutableAttributedString2.append(boldAttributedString)
mutableAttributedString2.append(NSAttributedString(string: "\n"))
mutableAttributedString2.append(regularAttributedString)
self.btnStatsPeople.setAttributedTitle(mutableAttributedString2, for: .normal)
UILabel has one line by default.
This property controls the maximum number of lines to use in order to
fit the label’s text into its bounding rectangle. The default value
for this property is 1. To remove any maximum limit, and use as many
lines as needed, set the value of this property to 0.
UIButton creates default UILabel. So using 0 lines is a solution for your problem:
self.btnStatsPeople.titleLabel?.numberOfLines = 0

best way to customize uilabel and make it internationalizable

I'm changing my app to make it localizable/internationalizable, by adding multiple languages, so I have some texts on the storyboard and others in the swift files, so I have to make them internationalizable, but I don't know how to keep a customized font and make it internationalizable.
I have created these:
So if I understand the first strings files are for UILabel which are written in the storyboard. The second is for text in swift files also UIlabel linked in.
But I have to customize, fonts, colours... for some texts, and I don't know how to do for the UILabel in the storyboard, but for swift files I did it:
var main_string = "VOTRE EXPERT DU\nREGROUPEMENT DE CRÉDITS\nEN FRANCE DEPUIS 1998."
var string_to_color = "1998"
var string_to_bold = "REGROUPEMENT DE CRÉDITS"
var range_color = (main_string as NSString).range(of: string_to_color)
var range_bold = (main_string as NSString).range(of: string_to_bold)
let attributedString = [ NSAttributedStringKey.font: UIFont(name: "gotham-book", size: 18.0)! ]
let myString = NSMutableAttributedString(string: "VOTRE EXPERT DU\nREGROUPEMENT DE CRÉDITS\nEN FRANCE DEPUIS 1998.", attributes: attributedString)
NSLocalizedString("Welcome", comment: "")
myString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.orange , range: range_color)
let font = UIFont(name: "gotham-bold", size: 18.0)
myString.addAttribute(NSAttributedStringKey.font, value: font, range: range_bold)
accueilTopLabel.attributedText = myString
But how can I manage different languages with? Because I use ranges so it looks difficult. What the best way to manage it?

How to get the selected string from a NSTextView in Swift?

How to do to get the selected string from a NSTextView in Swift?
// create a range of selected text
let range = mainTextField.selectedRange()
// this works but I need a plain string not an attributed string
let str = mainTextField.textStorage?.attributedSubstring(from: range)
Maybe I have to add an intermediate step where I get the full string and then apply the range on it?
What about
let str = mainTextField.text.substring(with: range)
Edit:
This should work now:
let range = mainTextField.selectedRange() // Returns NSRange :-/ (instead of Range)
let str = mainTextField.string as NSString? // So we cast String? to NSString?
let substr = str?.substring(with: range) // To be able to use the range in substring(with:)
The code snippet in the Swift 5. That's not very hard but repeated
let string = textView.attributedString().string
let selectedRange = textView.selectedRange()
let startIndex = string.index(string.startIndex, offsetBy: selectedRange.lowerBound)
let endIndex = string.index(string.startIndex, offsetBy: selectedRange.upperBound)
let substring = textView.attributedString().string[startIndex..<endIndex]
let selectedString = String(substring)
In case anyone is having issues with the selectedRanges() not returning the proper range for an NSTextView, make sure that you have made your NSTextView selectable. I don't know if it's not selectable by default but I had to enable it;
textView.isSelectable = true
I was trying this in Swift 5 using #user25917 code sample above and I couldn't get the ranges no matter what. I was getting a visual confirmation the text was selected through highlighting which threw me off. This was driving me mad for a few hours.
This may be helpfull for you :
let textView = NSTextView(frame: NSMakeRect(0, 0, 100, 100))
let attributes = [NSForegroundColorAttributeName: NSColor.redColor(),
NSBackgroundColorAttributeName: NSColor.blackColor()]
let attrStr = NSMutableAttributedString(string: "my string", attributes: attributes)
let area = NSMakeRange(0, attrStr.length)
if let font = NSFont(name: "Helvetica Neue Light", size: 16) {
attrStr.addAttribute(NSFontAttributeName, value: font, range: area)
textView.textStorage?.appendAttributedString(attrStr)
}

Possible error in NSMutableAttributedString

I am trying to change the font of an label with should be displayed in the UI. I've used this lines:
let myAttribute = [ NSFontAttributeName: UIFont(name: "cirth1", size: 18.0)! ]
let buttonTitleNSMut = NSMutableAttributedString(string: "\(buttonTitle)", attributes: myAttribute )
let buttonTitle:String = "\(buttonTitleNSMut)"
let button = createButtonWithTitle(buttonTitle as String)
But my output isn't the label in the different font, but a long string with all the "specs" of the font...
What am I doing wrong? Maybe the fact that in the end I say it is a String?
Try the code snippet below for what you are trying to achieve.
let plainText = "\(buttonTitle)" as NSString
let attributedText = NSMutableAttributedString(string: plainText as String)
attributedText.addAttribute(NSFontAttributeName: UIFont(name: "cirth1", size: 18.0)!)
button?.titleLabel?.attributedText = attributedText
Hope that helps.