问题
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