How to calculate UITextView first baseline position relatively to the origin

家住魔仙堡 提交于 2021-02-11 15:23:31

问题


How can I calculate UITextView first baseline position?

I tried calculating it this way:

self.textView.font!.descender + self.textView.font!.leading

However, the value I'm getting is not correct. Any ideas, hints?


回答1:


Based on the documentation zcui93 gives, font.ascender will give you the offset to the baseline within the font. To get the baseline of the font within the UITextView you need to add in textContainerInset.top:

extension UITextView {
    func firstBaseline() -> CGFloat {
        let font = self.font ?? UIFont.systemFontOfSize(UIFont.systemFontSize())
        return font.ascender + textContainerInset.top
    }
}

There's a little bit of assumption here in defaulting to the system font if no font is set, but I'm not sure what a better guess would be.

Running the following in the playground will demonstrate the effect:

class Container : UITextView {
    override func drawRect(rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()
        CGContextSaveGState(context)

        let containerRect = UIEdgeInsetsInsetRect(bounds, textContainerInset)
        UIColor(red: 1, green: 0, blue: 0, alpha: 0.25).setFill()
        CGContextFillRect(context, containerRect)

        let baseline = firstBaseline()

        UIColor(red: 1, green: 0, blue: 0, alpha: 0.75).setStroke()
        CGContextSetLineWidth(context, 1)
        CGContextMoveToPoint(context, containerRect.origin.x, baseline)
        CGContextAddLineToPoint(context, containerRect.origin.x + containerRect.width, baseline)
        CGContextStrokePath(context)

        super.drawRect(rect)
    }
}

let textView = Container(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
textView.font = UIFont.systemFontOfSize(UIFont.systemFontSize())
textView.text = "My Text"

And the result:




回答2:


There is a diagram from the Apple document

From my understanding, font.descender + font.leading gives the distance between the first baseline and starting of the second line.

I would imagine font.lineHeight would give you the right number, if UITextField doesn't have a secret padding.


EDIT

UITextField and UITextView shared same UIFont property.

For UITextView, there's an extra textContainerInset can be set.

EDIT 2

A further look at the UITextView gives more clue about what can be achieved:

It actually has a textContainer property, which is a NSTextContainer.

The NSTextContainer class defines a region in which text is laid out. An NSLayoutManager object uses one or more NSTextContainer objects to determine where to break lines, lay out portions of text, and so on.

And it's been used by layoutManager, theoretically the padding to the top of first line of text could be found by usedRectForTextContainer(_:).

I will need to test this once I have a Mac in hand. :)




回答3:


In my case I was extending UITextField class and I just wanted to draw a line in the textfield baseline and I succeed with the following chunk:

self.svwLine = UIView(frame: CGRectMake(0,self.frame.size.height+(self.font?.descender)!,self.frame.size.width,2))
self.svwLine.backgroundColor = UIColor.whiteColor()
self.addSubview(self.svwLine)


来源:https://stackoverflow.com/questions/35922215/how-to-calculate-uitextview-first-baseline-position-relatively-to-the-origin

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!