NSAttributedString:适应容器的图片

12

我有一个NSAttributedString,它是由HTML创建的,并显示一些图片。问题是这些图片比容器大,我想知道如何让它们适应其中。

谢谢你的帮助

3个回答

24

我终于找到了怎样做:

content.enumerateAttribute(NSAttachmentAttributeName, inRange: NSMakeRange(0, content.length), options: NSAttributedStringEnumerationOptions(0)) { (value, range, stop) -> Void in
    if let attachement = value as? NSTextAttachment {
        let image = attachement.imageForBounds(attachement.bounds, textContainer: NSTextContainer(), characterIndex: range.location)
        let screenSize: CGRect = UIScreen.mainScreen().bounds
        if image.size.width > screenSize.width-2 {
            let newImage = image.resizeImage((screenSize.width-2)/image.size.width)
            let newAttribut = NSTextAttachment()
            newAttribut.image = newImage
            content.addAttribute(NSAttachmentAttributeName, value: newAttribut, range: range)
        }
    }
}

函数resizeImage()的定义如下:

extension UIImage {
    func resizeImage(scale: CGFloat) -> UIImage {
        let newSize = CGSizeMake(self.size.width*scale, self.size.height*scale)
        let rect = CGRectMake(0, 0, newSize.width, newSize.height)

        UIGraphicsBeginImageContext(newSize)
        self.drawInRect(rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    }
}

Swift 3 版本

text.enumerateAttribute(NSAttachmentAttributeName, in: NSMakeRange(0, text.length), options: .init(rawValue: 0), using: { (value, range, stop) in
    if let attachement = value as? NSTextAttachment {
        let image = attachement.image(forBounds: attachement.bounds, textContainer: NSTextContainer(), characterIndex: range.location)!
        let screenSize: CGRect = UIScreen.main.bounds
        if image.size.width > screenSize.width-20 {
            let newImage = image.resizeImage(scale: (screenSize.width-2)/image.size.width)
            let newAttribut = NSTextAttachment()
            newAttribut.image = newImage
            text.addAttribute(NSAttachmentAttributeName, value: newAttribut, range: range)
        }
    }
})

函数resizeImage()的定义如下:

func resizeImage(scale: CGFloat) -> UIImage {
    let newSize = CGSize(width: self.size.width*scale, height: self.size.height*scale)
    let rect = CGRect(origin: CGPoint.zero, size: newSize)

    UIGraphicsBeginImageContext(newSize)
    self.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage!
}

Swift 4 版本 + 扩展和可自定义的图片最大宽度

extension NSAttributedString {
    func attributedStringWithResizedImages(with maxWidth: CGFloat) -> NSAttributedString {
        let text = NSMutableAttributedString(attributedString: self)
        text.enumerateAttribute(NSAttributedStringKey.attachment, in: NSMakeRange(0, text.length), options: .init(rawValue: 0), using: { (value, range, stop) in
            if let attachement = value as? NSTextAttachment {
                let image = attachement.image(forBounds: attachement.bounds, textContainer: NSTextContainer(), characterIndex: range.location)!
                if image.size.width > maxWidth {
                    let newImage = image.resizeImage(scale: maxWidth/image.size.width)
                    let newAttribut = NSTextAttachment()
                    newAttribut.image = newImage
                    text.addAttribute(NSAttributedStringKey.attachment, value: newAttribut, range: range)
                }
            }
        })
        return text
    }
}

extension UIImage {
    func resizeImage(scale: CGFloat) -> UIImage {
        let newSize = CGSize(width: self.size.width*scale, height: self.size.height*scale)
        let rect = CGRect(origin: CGPoint.zero, size: newSize)

        UIGraphicsBeginImageContext(newSize)
        self.draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

8

Swift 4.2采用 @Nic Hubbard 的方法

let htmlString = "Put Your YourHTML String Here"

let setHeightUsingCSS = "<head><style type=\"text/css\"> img{ max-height: 100%; max-width: \(self.textView.frame.size.width) !important; width: auto; height: auto;} </style> </head><body> \(htmlString) </body>"

self.textView.attributedText = setHeightUsingCSS.html2AttributedString


extension Data {
    var html2AttributedString: NSAttributedString? {
        do {
            return try NSAttributedString(data: self, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
        } catch {
            print("error:", error)
            return  nil
        }
    }
    var html2String: String {
        return html2AttributedString?.string ?? ""
    }
}

extension String {
    var html2AttributedString: NSAttributedString? {
        return Data(utf8).html2AttributedString
    }
    var html2String: String {
        return html2AttributedString?.string ?? ""
    }
}

扩展参考


我已经尝试了上述方法,但解决方案并没有奏效,图像仍然超出屏幕。 - Prashanth
@Prashanth,我更新了我的答案。我忘记添加 !important}。请再试一次,它在我的应用程序上运行正常。 - ZAFAR007

4

您还可以将字符串包装在完整的HTML文档中,使用 CSS 调整图片大小。


1
不,不是NSAttributesString。在head标签中包含整个HTML文档和CSS。 - Nic Hubbard
哦,显然!谢谢。 - Florentin
@NicHubbard,你能提供一个CSS调整图片大小的例子吗? - Giorgio
1
@Giorgio 使用 img {max-width: %fpx; height: auto; text-align:center;} 并使用屏幕边界来设置 max-width - Nic Hubbard
某种方式,max-width:100%未能奏效......但其他属性如颜色可以,例如 <style>div { color: red !important;}</style>。 - Hardik Darji
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接