How to concatenate two UITextView - ios

I'm trying to concatenate two UItextView and it work.
They have different properties (for example different UIFont) but in the final UITextView they have the same properties. How to fix this?
textViewFirst!.text = "\n Example"
textViewFirst!.font = UIFont(name: "Helvetica Neue", size: 10);
textViewSecond.text = textViewSecond.text + textViewFirst.text

for example : this makes your text bold from the 4th char to 7th
let myFullString:String = textViewSecond.text + textViewFirst.text as String
var attributedText: NSMutableAttributedString = NSMutableAttributedString(string: myFullString)
attributedText.addAttributes([NSFontAttributeName: UIFont.boldSystemFontOfSize(14)], range: NSRange(location: 3, length: 3))
textViewSecond.attributedText = attributedText

Try this:
var attributedString = NSMutableAttributedString(string: textView2.text, attributes: [NSFontAttributeName : textView2.font])
attributedString.appendAttributedString(NSAttributedString(string: textView1.text, attributes: [NSFontAttributeName : textView1.font]))
textView2.attributedText = attributedString
In order to preserve both fonts and maybe other attributes (like text color) you must make use of NSAttributedString

let font = UIFont(name: "Helvetica Neue", size: 10.0) ?? UIFont.systemFontOfSize(18.0)
let textFont = [NSFontAttributeName:font]
// Create a string that will be our paragraph
let para1 = NSMutableAttributedString()
let para2 = NSMutableAttributedString()
// Create locally formatted strings
let attrString1 = NSAttributedString(string: "Hello ", attributes:textFont)
let attrString2 = NSAttributedString(string: "World ", attributes:textFont)
// Add locally formatted strings to paragraph
para1.appendAttributedString(attrString1)
para2.appendAttributedString(attrString2)
// Define paragraph styling
let paraStyle = NSMutableParagraphStyle()
paraStyle.firstLineHeadIndent = 15.0
paraStyle.paragraphSpacingBefore = 10.0
// Apply paragraph styles to paragraph
para1.addAttribute(NSParagraphStyleAttributeName, value: paraStyle, range: NSRange(location: 0,length: para1.length))
para2.addAttribute(NSParagraphStyleAttributeName, value: paraStyle, range: NSRange(location: 0,length: para1.length))
// Create UITextView
let view1 = UITextView(frame: CGRect(x: 0, y: 20, width: CGRectGetWidth(self.view.frame), height: 100))
let view2 = UITextView(frame: CGRect(x: 0, y: 100, width: CGRectGetWidth(self.view.frame), height: 100))
let view3 = UITextView(frame: CGRect(x: 0, y: 200, width: CGRectGetWidth(self.view.frame), height: 100))
// Add string to UITextView
view1.attributedText = para1
view2.attributedText = para2
var attributedString = NSMutableAttributedString(string: view1.text, attributes: [NSFontAttributeName : view1.font])
attributedString.appendAttributedString(NSAttributedString(string: view2.text, attributes: [NSFontAttributeName : view2.font]))
view3.attributedText = attributedString
// Add UITextView to main view
self.view.addSubview(view1)
self.view.addSubview(view2)
self.view.addSubview(view3)

Related

How to add an image with text to a PDFTableCell?

I need something like this (green square):
enter image description here
I've tried adding attributedString with an image attached to the cell, but that doesn't work. Do you have any ideas?
let attachmentImage = NSTextAttachment()
attachmentImage.image = serviceImage.image
attachmentImage.bounds = CGRect(x: 0, y: 0, width: 14, height: 14)
let attrString = NSMutableAttributedString(
string: "Text followed by an image",
attributes: [
.font: regularFont
])
attrString.append(NSAttributedString(attachment: attachmentImage))
let imageCell = table[position: PDFTableCellPosition(row: 0, column: 0)]
imageCell.content = try? PDFTableContent(content: attrString)

UITextContainerView hidding clickable link of UITextView

I made a clickable link in a UITextView using NSMutableAttributeString.
All it changes is that the text is highlighted
As we can see : floating over my UITextView there is a UIContainerView (I really don't know if its because of that.. I'm trying)
Here is my UIView code:
class InfoBox: UIView {
let Heading: UITextView = {
let textView = UITextView(frame: CGRect(x: 15, y: 0, width: 200, height: 35))
textView.font = UIFont.systemFont(ofSize: 20)
textView.textColor = UIColor.white
textView.isScrollEnabled = false
textView.backgroundColor = UIColor.clear
textView.isEditable = false
textView.isSelectable = true
return textView
}()
let TextContent: UITextView = {
let textView = UITextView(frame: CGRect(x: 15, y: 27, width: UIScreen.main.bounds.width, height: 30))
textView.font = UIFont.systemFont(ofSize: 17)
textView.textColor = UIColor.white
textView.isScrollEnabled = false
textView.backgroundColor = UIColor.clear
textView.isEditable = false
textView.isSelectable = true
return textView
}()}
The NSAttributedString code:
func transformText(text: String, underlined: Bool, linkURL: String) -> NSAttributedString {
let textRange = NSMakeRange(0, text.characters.count)
let attributedText = NSMutableAttributedString(string: text)
if underlined{
attributedText.addAttribute(NSUnderlineStyleAttributeName , value: NSUnderlineStyle.styleSingle.rawValue, range: textRange)
attributedText.addAttribute(NSUnderlineColorAttributeName , value: UIColor.lightGray, range: textRange)
}
attributedText.addAttribute(NSFontAttributeName , value: UIFont(name: "Helvetica-Light", size: 17)!, range: textRange)
attributedText.addAttribute(NSForegroundColorAttributeName , value: UIColor.lightGray, range: textRange)
if(linkURL != "")
{
let attrib = [NSLinkAttributeName: NSURL(string: linkURL)!]
attributedText.addAttributes(attrib, range: textRange)
}
return attributedText
}
And this is how it is called:
self.TelBox.TextContent.attributedText = transformText(text: self.TelBox.TextContent.text, underlined: true, linkURL: "https://www.google.fr")
Secondary question : is it possible to make a clickable link in a UITextView for a telephone number so that when clicked it calls that number? Did it with a UIButton .
I am not sure what is wrong with your UIContainerView, as far as i can see there's nothing wrong there.
Here's the method to make the link call a number:
func transformText(text: String, underlined: Bool, phoneNumber: String) -> NSAttributedString {
let textRange = NSMakeRange(0, text.characters.count)
let attributedText = NSMutableAttributedString(string: text)
if underlined{
attributedText.addAttribute(NSAttributedStringKey.underlineStyle , value: NSUnderlineStyle.styleSingle.rawValue, range: textRange)
attributedText.addAttribute(NSAttributedStringKey.underlineColor , value: UIColor.lightGray, range: textRange)
}
attributedText.addAttribute(NSAttributedStringKey.font , value: UIFont(name: "Helvetica-Light", size: 17)!, range: textRange)
attributedText.addAttribute(NSAttributedStringKey.foregroundColor , value: UIColor.lightGray, range: textRange)
if(phoneNumber != "")
{
let attrib = [
NSAttributedStringKey.link: URL(string: "tel://" + phoneNumber.replacingOccurrences(of: " ", with: ""))]
attributedText.addAttributes(attrib, range: textRange)
}
return attributedText
}
You can use it like this: TextContent.attributedText = transformText(text: "12345", underlined: true, phoneNumber: "12345")

why multiline attributedString UITextView has a different line height?

I get different line height in textView with using same font
How to set fixed line height?
I have done a lot of attempts, any help is appreciated, thanks
set NSMutableParagraphStyle lineSpacing is useless
set lineHeightMultiple is to make the difference more obvious
[
demo
import UIKit
import PlaygroundSupport
let view = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 1000))
let data: [String] = [
"商品名称: 巧克力",
"商品名称: 巧克力",
"商品名称: 巧克力",
"注册未成功,请验证电子邮件",
"注册未成功,请验证电子邮件",
"注册未成功,请验证电子邮件",
"测试文字, 测试文字,测试文字",
"测试文字, 测试文字,测试文字",
"测试文字, 测试文字,测试文字",
]
let textView = UITextView(frame: view.frame)
let paragraphStyle = NSMutableParagraphStyle()
let bodyFont = UIFont.systemFont(ofSize: 20.0)
paragraphStyle.lineHeightMultiple = 4
var stripe = false
// attributedString
let mutableAttributedString = NSMutableAttributedString(string: "Test TextViewAttributedString\n", attributes: [
NSFontAttributeName: UIFont.systemFont(ofSize: 18.0)
])
for text: String in data {
var backgroundColor = UIColor(red:0.13, green:0.38, blue:0.95, alpha:1.00)
if stripe {
backgroundColor = UIColor(red:0.92, green:0.12, blue:0.38, alpha:1.00)
}
let contentAttributedString = NSAttributedString(string: text, attributes: [
NSBackgroundColorAttributeName: backgroundColor,
NSParagraphStyleAttributeName: paragraphStyle,
NSFontAttributeName: bodyFont
])
mutableAttributedString.append(contentAttributedString)
stripe = !stripe
// add newline character
let newlineAttributedString = NSAttributedString(string: "\n")
mutableAttributedString.append(newlineAttributedString)
}
textView.attributedText = mutableAttributedString
view.addSubview(textView)
PlaygroundPage.current.liveView = view
I found the reason, the newlineAttributedString also need NSFontAttributeName
let newlineAttributedString = NSAttributedString(string: "\n", attributes: [
NSFontAttributeName: bodyFont
])
mutableAttributedString.appendAttributedString(newlineAttributedString)

NSKernAttributeName space at end of line in an NSAttributedString

When using NSKernAttributeName it puts a space at the end of each line, is there any way to fix this? I can set the attributed to be in the range of:
NSRange(location: 0, length: self.text!.characters.count-1)
But I don't want to set this for every line.
This is the test code in the a playground I am using
//: Playground - noun: a place where people can play
import UIKit
import XCPlayground
var text = "Hello, playground\nhow are you?"
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.paragraphSpacing = 50
paragraphStyle.alignment = NSTextAlignment.Left
paragraphStyle.lineBreakMode = NSLineBreakMode.ByTruncatingTail
let attributes = [
NSParagraphStyleAttributeName: paragraphStyle
, NSKernAttributeName: 20
]
let attributedString = NSAttributedString(string: text, attributes: attributes)
let label = UILabel()
label.attributedText = attributedString
label.numberOfLines = 0
label.textColor = UIColor.greenColor()
label.backgroundColor = UIColor.orangeColor()
label.sizeToFit()
label.center = CGPoint(x: 500, y: 100)
var text2 = "What's up\nWhere are you?"
let attributedString2 = NSAttributedString(string: text2, attributes: attributes)
let label2 = UILabel()
label2.attributedText = attributedString2
label2.numberOfLines = 0
label2.textColor = UIColor.greenColor()
label2.backgroundColor = UIColor.orangeColor()
label2.sizeToFit()
label2.center = CGPoint(x: 500, y: 250)
var text3 = "Hello"
let attributedString3 = NSAttributedString(string: text3, attributes: attributes)
let label3 = UILabel()
label3.attributedText = attributedString3
label3.numberOfLines = 0
label3.textColor = UIColor.greenColor()
label3.backgroundColor = UIColor.orangeColor()
label3.sizeToFit()
label3.center = CGPoint(x: 500, y: 400)
let holderView = UIView(frame: CGRect(x: 0, y: 0, width: 1000, height: 500))
holderView.backgroundColor = UIColor.lightGrayColor()
holderView.addSubview(label)
holderView.addSubview(label2)
holderView.addSubview(label3)
XCPlaygroundPage.currentPage.liveView = holderView
With the result looking like this:
You can see the spaces at the end of each of the lines.
This is actually the definition of how kerning works; it adjusts the space between the kerned character and where the next character will be. Whether a next character proceeds to be drawn or not is irrelevant.
Standard Attributes
The kerning attribute indicates how much the following character should be shifted from its default offset as defined by the current character’s font; a positive kern indicates a shift farther along and a negative kern indicates a shift closer to the current character.
If it helps, think about doing this in a word processor. If kerning is on, and you type a character, where would you expect the insertion point to be then? The expected answer would be "offset from the just typed character by the amount of kern" as that's what happens in the default case of kern being 0, correct? Well, that's exactly what's happening here: if you kern the last character of a string, the string therefore includes the last kern.
So the correct thing to do here is to wrap up your dropLast() logic in an extension and call it a day.
Create an extension
import UIKit
extension UILabel {
#IBInspectable var kerning: Float {
get {
var range = NSMakeRange(0, (text ?? "").characters.count)
guard let kern = attributedText?.attribute(NSKernAttributeName, atIndex: 0, effectiveRange: &range),
value = kern as? NSNumber
else {
return 0
}
return value.floatValue
}
set {
var attText:NSMutableAttributedString?
if let attributedText = attributedText {
attText = NSMutableAttributedString(attributedString: attributedText)
} else if let text = text {
attText = NSMutableAttributedString(string: text)
} else {
attText = NSMutableAttributedString(string: "")
}
let range = NSMakeRange(0, attText!.length)
attText!.addAttribute(NSKernAttributeName, value: NSNumber(float: newValue), range: range)
self.attributedText = attText
}
}
}
This was answered here

NSAttributedString not displaying correctly

I want my UILabel to be able to split a long name into two lines and add the hyphen. Currently my code is like so :
let usernameX = profilePhoto.frame.size.width+horizontalMargin
let username = UILabel(frame: CGRect(x: usernameX, y: (self.frame.size.height/2)-21, width: self.frame.size.width-usernameX-horizontalMargin, height: 42))
username.adjustsFontSizeToFitWidth = true
username.font = UIFont(name: "SFUIDisplay-Regular", size: 20)
username.minimumScaleFactor = 0.8
username.numberOfLines = 2
username.translatesAutoresizingMaskIntoConstraints = false
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.hyphenationFactor = 0.5
let attributedString = NSMutableAttributedString(string: "Areallylongname", attributes: [NSParagraphStyleAttributeName: paragraphStyle])
However the label is only displaying "Areally-". What am I doing wrong here?
You can re-check the height of superview of label.
Fixing 42 as height is not the correct way to do it. You can calculate height of the label required dynamically and assign it. You can do it following way.
let attributedString = NSMutableAttributedString(string: "Areallylongname", attributes: [NSParagraphStyleAttributeName: paragraphStyle, NSFontAttributeName : UIFont(name: "SFUIDisplay-Regular", size: 20)])
var newFrame = attributedString.boundingRectWithSize(CGSizeMake(username.frame.size.width, 9999), options: NSStringDrawingOptions.UsesLineFragmentOrigin , context: nil)
newFrame.origin.x = username.frame.origin.x
newFrame.origin.y = username.frame.origin.y
You can set the new frame in viewDidLayoutSubviews

Resources