简体   繁体   中英

Get number of lines in UITextView without contentSize.height

I'm creating an image to export in my iOS app. I am using UIGraphicsBeginImageContext to draw the elements of the image but I've been struggling drawing a UITextView in the image.

First I create a parent view for rendering:

var parentView : UIView = UIView(frame: CGRectMake(0, 0, 700, 700))

Then I programatically create the textView and add all the properties. I give it x=100 and y=100 to align the text in the image. Width = 500 is good to have a margin of 100px on each side:

var textView: UITextView = UITextView(frame: CGRectMake(100, 100, 500, 350))
textView.text = myText
textView.textContainerInset = UIEdgeInsetsMake(20, 20, 20, 20)
textView.backgroundColor = UIColor(red: 255, green: 255, blue: 255, alpha: 0.70)
textView.font = UIFont(name: "Helvetica Neue Light Italic", size: 35)

Then I render the textview in context by adding it as a subview to the parent view and then I get the image for export:

parentView.addSubview(textView)        
parentView.layer.renderInContext(UIGraphicsGetCurrentContext())    
var newIMG = UIGraphicsGetImageFromCurrentImageContext()

The problem is that the height is fixed to 350px, but sometimes the text is not long enough to use all that area. Ideally I would like to know how many lines will my text use, so I can give it a proportional height and not have a white unused area (see pic for example):

信息 Any ideas on how to render the text view with a proportional height? Thanks a lot!

I found the perfect solution to this problem in Apple's Text Layout Programming Guide . The solution Apple provides is in Objective-C, so I tested and re-wrote it for Swift.

Both methods work great and return the number of lines that are being used in a UITextView, without funky math and 100% accurate every time. 行数,而无需进行时髦的数学运算,并且每次都可以100%准确。

extension UITextView {
    func numberOfLines() -> Int {
        let layoutManager = self.layoutManager
        let numberOfGlyphs = layoutManager.numberOfGlyphs
        var lineRange: NSRange = NSMakeRange(0, 1)
        var index = 0
        var numberOfLines = 0

        while index < numberOfGlyphs {
            layoutManager.lineFragmentRectForGlyphAtIndex(
                index, effectiveRange: &lineRange
            )
            index = NSMaxRange(lineRange)
            numberOfLines += 1
        }
        return numberOfLines
    }
}

Just call this directly on your UITextView like so: myTextView.numberOfLines() <- returns an Int


func numberOfLines(textView: UITextView) -> Int {
    let layoutManager = textView.layoutManager
    let numberOfGlyphs = layoutManager.numberOfGlyphs
    var lineRange: NSRange = NSMakeRange(0, 1)
    var index = 0
    var numberOfLines = 0

    while index < numberOfGlyphs {
        layoutManager.lineFragmentRectForGlyphAtIndex(index, effectiveRange: &lineRange)
        index = NSMaxRange(lineRange)
        numberOfLines += 1
    }
    return numberOfLines
}

Just call numberOfLines(myTextView) to retrieve an Int of the number of lines

I didn't find a way to get the number of lines, but I managed to remove all that white space using textView.sizeToFit(). It worked great, hopefully someone will find this useful!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM