jbr*_*nan 8 cocoa-touch nslayoutmanager uitextview ios textkit
我有一个自定义NSLayoutManager子类,用于绘制药丸状标记。我为带有自定义属性(TokenAttribute)的子字符串绘制了这些标记。我没问题。
但是,我需要在范围周围添加一点“填充” TokenAttribute(这样标记的圆角矩形背景将不会与文本相交)。
在上图中,我正在用橙色绘制令牌的背景,但我想在周围加些填充,469以使背景不紧贴文本。
我不太确定该怎么做。我尝试重写-boundingRectForGlyphRange:inTextContainer:以返回具有更多水平填充的边界矩形,但字形的布局实际上并不受此影响。
如何在某些字形/字形范围内增加间距?
这是我用于在布局管理器子类中绘制背景的代码:
- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin {
NSTextStorage *textStorage = self.textStorage;
NSRange glyphRange = glyphsToShow;
while (glyphRange.length > 0) {
NSRange characterRange = [self characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL];
NSRange attributeCharacterRange;
NSRange attributeGlyphRange;
id attribute = [textStorage attribute:LAYScrubbableParameterAttributeName
atIndex:characterRange.location
longestEffectiveRange:&attributeCharacterRange
inRange:characterRange];
attributeGlyphRange = [self glyphRangeForCharacterRange:attributeCharacterRange
actualCharacterRange:NULL];
attributeGlyphRange = NSIntersectionRange(attributeGlyphRange, glyphRange);
if (attribute != nil) {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
UIColor *backgroundColor = [UIColor orangeColor];
NSTextContainer *textContainer = self.textContainers[0];
CGRect boundingRect = [self boundingRectForGlyphRange:attributeGlyphRange inTextContainer:textContainer];
// Offset this bounding rect by the `origin` passed in above
// `origin` is the origin of the text container!
// if we don't do this, then bounding rect is incorrectly placed (too high, in my case).
boundingRect.origin.x += origin.x;
boundingRect.origin.y += origin.y;
[backgroundColor setFill];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:boundingRect cornerRadius:boundingRect.size.height / 2.0];
[path fill];
[super drawGlyphsForGlyphRange:attributeGlyphRange atPoint:origin];
CGContextRestoreGState(context);
} else {
[super drawGlyphsForGlyphRange:glyphsToShow atPoint:origin];
}
glyphRange.length = NSMaxRange(glyphRange) - NSMaxRange(attributeGlyphRange);
glyphRange.location = NSMaxRange(attributeGlyphRange);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
NSLayoutManagerDelegate 中定义了一些方法,用作基于字形的自定义点。
使用
func layoutManager(_ layoutManager: NSLayoutManager, shouldGenerateGlyphs glyphs: UnsafePointer<CGGlyph>, properties props: UnsafePointer<NSLayoutManager.GlyphProperty>, characterIndexes charIndexes: UnsafePointer<Int>, font aFont: NSFont, forGlyphRange glyphRange: NSRange) -> Int
Run Code Online (Sandbox Code Playgroud)
识别与您感兴趣的范围周围的空白相关的字形,并通过将props数组中的值更改为NSLayoutManager.GlyphProperty.controlCharacter来标记这些字形。然后将这个改变的数组传递给
NSLayoutManager.setGlyphs(_:properties:characterIndexes:font:forGlyphRange:)
Run Code Online (Sandbox Code Playgroud)
之后,您可以实施
func layoutManager(_ layoutManager: NSLayoutManager, shouldUse action: NSLayoutManager.ControlCharacterAction, forControlCharacterAt charIndex: Int) -> NSLayoutManager.ControlCharacterAction
Run Code Online (Sandbox Code Playgroud)
再次识别感兴趣的字形并返回预定义的操作:
NSLayoutManager.ControlCharacterAction.whitespace
Run Code Online (Sandbox Code Playgroud)
最后,这可以让您实现
func layoutManager(_ layoutManager: NSLayoutManager, boundingBoxForControlGlyphAt glyphIndex: Int, for textContainer: NSTextContainer, proposedLineFragment proposedRect: NSRect, glyphPosition: NSPoint, characterIndex charIndex: Int) -> NSRect
Run Code Online (Sandbox Code Playgroud)
更改用于字形的边界框。只需返回适当的尺寸即可。这将对以下布局机制产生影响。
祝你好运!
| 归档时间: |
|
| 查看次数: |
795 次 |
| 最近记录: |