I have the HTML text, which I want to convert to NSAttributedString, all works fine, but one problem, I want to display blockquote tag with a vertical line on the left side, I want this line to be 3px width, but it seems that width is ignored. How I change the width of this div?
Here is my code.
What I'm doing wrong?
public class func NSStringToAttributed(_ nsText: String,
font: UIFont = UIFont.systemFont(ofSize: 15.0)) -> NSMutableAttributedString? {
let stringWithFont = (NSString(string: nsText).appendingFormat("<style>body{font-family: '%#'; font-size:%fpx;}</style>",
".SFUIText",
font.pointSize))
let parsedCommentHTML = stringWithFont.replacingOccurrences(of: "<blockquote>",
with: "<div style=\"max-width: 3px; background: #82a43a; height: transform:translateY();\"><i style=\"color:#A9A9A9\"><blockquote>\n").replacingOccurrences(of: "</blockquote>",
with: "</blockquote></i></div>")
if let data = String(parsedCommentHTML).data(using: .unicode,
allowLossyConversion: false) {
let style = NSMutableParagraphStyle()
style.minimumLineHeight = 20.0
style.headIndent = 6.0
style.firstLineHeadIndent = 6.0
style.alignment = .left
let attributes = [
NSParagraphStyleAttributeName: style ]
if let attrString = try? NSMutableAttributedString(data: data,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil) {
attrString.addAttributes(attributes,
range: NSString(string: attrString.string).range(of: attrString.string))
attrString.addAttribute(NSKernAttributeName,
value: -0.2,
range: NSString(string: attrString.string).range(of: attrString.string))
return attrString
}
}
And here is result
Related
Hi guys I have small problem, I'm using func:
static func convertFromHTMLString(_ input: String?) -> NSAttributedString? {
guard let input = input else { return nil }
guard let data = input.data(using: String.Encoding.unicode, allowLossyConversion: true) else { return nil }
return try? NSAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType : NSAttributedString.DocumentType.html], documentAttributes: nil)
}
to read my Strings from Localizable.strings with attributes like this:
But when I run my app it looks that:
This change my Label color to black and font size to something like 10-12 ;/
My Label should have white color and font size 17, anyone know how to fix it?
Thanks ! :)
#Edit1
The solution must look like this
This is how it looks on Android.
func convertFromHTMLString(_ input: String?) -> NSAttributedString? {
guard let input = input else { return nil }
guard let data = input.data(using: String.Encoding.unicode, allowLossyConversion: true) else { return nil }
if let string = try? NSAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType : NSAttributedString.DocumentType.html], documentAttributes: nil).string
{
//Set color and font
let myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.white , NSAttributedString.Key.font: UIFont(name: "Chalkduster", size: 17.0)! ]
let myAttrString = NSAttributedString(string: string, attributes: myAttribute)
return myAttrString
}
return nil
}
I have a string that contains HTML code. What is the best way to display that (it contains images), also I want to make links in that tappable (open in Safari)
I have tried String extension that gives me NSAttributedString from HTML, but the image is only partially shown and links are not tappable.
let text = htmlString.attributedString(withRegularFont: UIFont.systemFont(ofSize: 14), andBoldFont: UIFont.systemFont(ofSize: 16))
extension String {
func attributedString(withRegularFont regularFont: UIFont, andBoldFont boldFont: UIFont, textColor: UIColor = UIColor.gray) -> NSMutableAttributedString {
var attributedString = NSMutableAttributedString()
guard let data = self.data(using: .utf8) else { return NSMutableAttributedString() }
do {
attributedString = try NSMutableAttributedString(data: data,
options: [.documentType: NSAttributedString.DocumentType.html,
.characterEncoding:String.Encoding.utf8.rawValue],
documentAttributes: nil)
let range = NSRange(location: 0, length: attributedString.length)
attributedString.enumerateAttribute(NSAttributedString.Key.font, in: range, options: .longestEffectiveRangeNotRequired) { value, range, _ in
let currentFont: UIFont = value as! UIFont
var replacementFont: UIFont? = nil
if currentFont.fontName.contains("bold") || currentFont.fontName.contains("Semibold") {
replacementFont = boldFont
} else {
replacementFont = regularFont
}
let replacementAttribute = [NSAttributedString.Key.font:replacementFont!, NSAttributedString.Key.foregroundColor: textColor]
attributedString.addAttributes(replacementAttribute, range: range)
} catch let e {
print(e.localizedDescription)
}
return attributedString
}
}
It shows me the HTML inside the UILabel but I am not able to tap on links and images are cropped respective to device width.
I think that the best option is to save this html string as a file and then load this file using web view.
check this question
I am using Text View in Scroll View to load html content like the code below. Everything works fine when test on device. But when I test on simulator, the content disappear but you still can copy/paste them. See the no content image. This case happens when the html string too long.
It will work when I delete the css "font-family: (font!.fontName); font-size: (font!.pointSize)" or disable the "scrolling enable" of text view.
Any advices are welcome, thanks!
let screenWidth = htmlContentTv.frame.width - 10
let font = UIFont(name: "Univers-Light", size: 16)
let html = "<html><head><style>img{max-width:\(screenWidth)px;height:auto !important;width:auto !important;};</style> </head>" + "<body><div style=\"font-family: \(font!.fontName); font-size: \(font!.pointSize);color: #000000; line-height:1.5;\">%#</div></body></html>"
let processHtml = String(format: html, article.content!)
do {
let attrStr = try NSAttributedString(
data: processHtml.data(using:.unicode, allowLossyConversion: true)!,
options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSFontAttributeName: font!],
documentAttributes: nil)
htmlContentTv.attributedText = attrStr
} catch let error {
print("html error \(error)" )
}
It is not good way to show html text, if you do not have clear reason to use UITextView, you can you use for this case UIWebView:
webView.loadHTMLString(htmlText, baseURL: nil)
And if you need change color or font you can use this extension
extension String
{
func htmlFormattedString(font:UIFont, color: UIColor) -> String
{
let numberOfColorComponents:Int = color.cgColor.numberOfComponents
let colorComponents = color.cgColor.components
var colorHexString = ""
if numberOfColorComponents == 4 {
let red = (colorComponents?[0])! * 255
let green = (colorComponents?[1])! * 255
let blue = (colorComponents?[2])! * 255
colorHexString = NSString(format:"%02X%02X%02X", Int(red), Int(green), Int(blue)) as String
} else if numberOfColorComponents == 2 {
let white = (colorComponents?[0])! * 255
colorHexString = NSString(format:"%02X%02X%02X", Int(white), Int(white), Int(white)) as String
} else {
return "Color format noch supported"
}
return NSString(format: "<html>\n <head>\n <style type=\"text/css\">\n body {font-family: \"%#\"; font-size: %#; color:#%#;}\n </style>\n </head>\n <body>%#</body>\n </html>", font.familyName, String(stringInterpolationSegment: font.pointSize), colorHexString, self) as String
}
}
To use it you just call htmlText.htmlFormattedString(font:someFont,color:.red) before you load text to WebView
I want to display text in Italic ,bold which is received from server .
< p > < b > < i > hello < /i > < /b > < i >world< /i >< /p > so,
responseObj!["text"] = "<p><b><i>hello</i></b><i>world</></p>"
if let postText:String = responseObj!["text"] as? String{
let str = try NSAttributedString(data: postText.data(using: String.Encoding.unicode, allowLossyConversion: true)!, options: [ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
self.textView.attributedText = str
}
when i am adding like this means my text displays normal without applying bold & italic . I want text to be displayed in bold ,italic .
EDIT: Updated Swift 4
Create an extension for String:
extension String {
func htmlAttributedString(fontSize: CGFloat = 17.0) -> NSAttributedString? {
let fontName = UIFont.systemFont(ofSize: fontSize).fontName
let string = self.appending(String(format: "<style>body{font-family: '%#'; font-size:%fpx;}</style>", fontName, fontSize))
guard let data = string.data(using: String.Encoding.utf16, allowLossyConversion: false) else { return nil }
guard let html = try? NSMutableAttributedString (
data: data,
options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil) else { return nil }
return html
}
}
Invoke it anywhere in your project:
text.htmlAttributedString() // will set fontSize with 17.0 which is the default value
text.htmlAttributedString(fontSize: 14.0) // pass your required fontSize
Note, that let string = self.appending(String(format: "<style>body{font-family: '%#'; font-size:%fpx;}</style>", fontName, fontSize)) is used to keep the string font as same as the font used in default iOS platform.
To set the string on UITextView use:
textView.attributedText = textToBeConverted.htmlAttributedString() ?? ""
RESULT:
Assign Attributed text to UITextView from below function,
//HTML to Attributed text
func stringFromHtml(string: String) -> NSAttributedString? {
do {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
if let d = data {
let str = try NSAttributedString(data: d,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
return str
}
} catch {
}
return nil
}
//This will give you attributed text which you have to assign to your UITextView. and whatever string having html tag that you have to pass inside this function.
//Below code will conver attributed text to HTML Text
//Attributed to HTML text
let attrStr = self.txtView.attributedText
let documentAttributes = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType]
do {
let htmlData = try attrStr?.data(from: NSMakeRange(0, (attrStr?.length)!), documentAttributes:documentAttributes)
if let htmlString = String(data:htmlData!, encoding:String.Encoding.utf8) {
print(htmlString)
}
}
catch {
print("error creating HTML from Attributed String")
}
My image
I am getting data from Html to the text.
Now please tell me how to avoid the space between two paragraphs ?
func processGetDescriptionResponse(json: JSON) {
let status = json.dictionaryObject!["status"] as? Bool
if status == true {
let data = json.dictionaryValue["data"]!
let values = data.arrayValue
dataSourceDescription.removeAll()
for i in 0 ..< values.count {
let description = Description.initWithJSON(values[i])
dataSourceDescription.append(description)
// DetailDescription.text = dataSourceDescription[i].content
if dataSourceDescription[i].file_url == ""
{
DetailImage.image = UIImage(named: "logo_two_fifty")
}
else
{
let imageURL = NSURL(string: baseURLString + dataSourceDescription[i].file_url!)
DetailImage.kf_setImageWithURL(imageURL!, placeholderImage: nil, optionsInfo: [.Transition(ImageTransition.Fade(50))]) { (image, error, cacheType, imageURL) in
}
}
DetailDescription.attributedText = convertText(dataSourceDescription[i].content!)
print(DetailDescription.text)
}
} else {
}
}
If you receive html content, you can display it in UITextView using NSAttributedString:
let htmlString = "<html><body><p>Para 1</p><p>Para 2</p></body></html>"
let attributedString = try!
NSAttributedString(data: htmlString.dataUsingEncoding(NSUnicodeStringEncoding, allowLossyConversion: false)!,
options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
documentAttributes: nil)
yourTextView.attributedText = attributedString