Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 控制NSLayoutManager中自定义文本属性周围的间距_Ios_Cocoa Touch_Uitextview_Textkit_Nslayoutmanager - Fatal编程技术网

Ios 控制NSLayoutManager中自定义文本属性周围的间距

Ios 控制NSLayoutManager中自定义文本属性周围的间距,ios,cocoa-touch,uitextview,textkit,nslayoutmanager,Ios,Cocoa Touch,Uitextview,Textkit,Nslayoutmanager,我有一个自定义的NSLayoutManager子类,用于绘制药丸形状的令牌。我使用自定义属性(TokenAttribute)为子字符串绘制这些标记。我画不成问题 但是,我需要在带有标记属性的范围周围添加一点“填充”(以便标记的圆形矩形背景不会与文本相交) 在上图中,我正在用橙色绘制令牌的背景,但我需要在469周围添加额外的填充,这样背景就不会正好与文本相对 我真的不知道该怎么做。我尝试重写-boundingrectforglyprange:inTextContainer:以返回具有更多水平填充

我有一个自定义的
NSLayoutManager
子类,用于绘制药丸形状的令牌。我使用自定义属性(
TokenAttribute
)为子字符串绘制这些标记。我画不成问题

但是,我需要在带有
标记属性的范围周围添加一点“填充”(以便标记的圆形矩形背景不会与文本相交)

在上图中,我正在用橙色绘制令牌的背景,但我需要在
469
周围添加额外的填充,这样背景就不会正好与文本相对

我真的不知道该怎么做。我尝试重写
-boundingrectforglyprange:inTextContainer:
以返回具有更多水平填充的边界矩形,但glyph的布局似乎实际上不受此影响

如何在某些字形/字形范围周围提供更多间距?


以下是我在布局管理器子类中绘制背景的代码:

- (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);
    }
}

NSLayoutManagerDelegate中定义了一些方法,它们用作基于图示符的自定义点

使用

func布局管理器(\layoutManager:NSLayoutManager,shouldGenerateGlyphs glyphs glyphs:UnsafePointer,properties props:UnsafePointer,characterIndexes charIndexes:UnsafePointer,font-aFont:NSFont,forglyprange glyphRange glyphRange:NSRange)->Int
识别与感兴趣范围周围的空白相关联的标志符号,并通过将其在props数组中的值更改为NSLayoutManager.GlyphProperty.controlCharacter来标记这些标志符号。 然后将修改后的数组传递给

NSLayoutManager.setGlyphs(uquo:properties:characterIndex:font:forglyprange:)
之后,您可以执行

func layoutManager(\layoutManager:NSLayoutManager,应使用操作:NSLayoutManager.ControlCharacterAction,forControlCharacterAt charIndex:Int)->NSLayoutManager.ControlCharacterAction
要再次识别感兴趣的图示符并返回预定义操作,请执行以下操作:

NSLayoutManager.ControlCharacterAction.whitespace
最后,这让您可以实现

func布局管理器(\layoutManager:NSLayoutManager,boundingBoxForControlGlyphAt glyphIndex:Int,对于textContainer:NSTextContainer,proposedLineFragment proposedRect:NSRect,glyphPosition:NSPoint,characterIndex charIndex:Int)->NSRect
更改用于图示符的边界框。只需返回适当的维度。这将对以下布局机制产生影响


祝你好运

我不是大师,但我已经在TextKit中低头一段时间了。你用什么画背景?你能显示一点代码吗?为什么不能修改
boundingRect
并将其放大一点?rect不应该被剪裁,因此如果你再添加一点填充,它应该可以工作。@我可以修改
boundingRect
,它会按预期画得更大,但文本的布局不受影响,因此标记可以插入到其他文本中,太:\n这是我想要避免的。看看在自定义文本容器中重写
lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:
是否会奏效。看起来您的布局管理器在为boundingRect查询文本容器,而这可能是修改它的正确位置。@太棒了!这正是我一直在寻找的!在NSLayoutManager中尝试这样做非常困难。NSTextContainer在这方面很好。这很好!我没有意识到
layoutManager:boundingBoxForControlGlyphAt:…
仅为
控件字符调用。谢谢