У меня есть собственный подкласс 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);
}
}
boundingRect
и сделать его немного больше? Прямоугольник не должен обрезаться, поэтому, если вы добавите немного больше отступов, он должен работать. - person Moshe   schedule 29.12.2015boundingRect
, и он станет больше, как и ожидалось, но макет текста не изменится, поэтому токены также могут натыкаться на другой текст:\ чего я хочу избежать. - person jbrennan   schedule 29.12.2015lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:
в пользовательском текстовом контейнере. Похоже, ваш менеджер компоновки консультируется с текстовым контейнером для этого boundingRect, и это может быть правильным местом для его изменения. - person Moshe   schedule 29.12.2015boundingRect
и столкнулся с теми же проблемами, что и вы. Я также играл сfunc setLocation(CGPoint, forStartOfGlyphRange: NSRange)
, и хотя это многообещающе, я не могу найти надежный способ, чтобы дополнение стало кумулятивным (например, если у меня есть несколько подстрок сTokenAttribute
). Часть меня задается вопросом, потребует ли это погружения в механизм набора текста. - person Cory Juhlin   schedule 06.05.2019lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect
позволяет вам изменять прямоугольник строки, но вы получаете обратные вызовы только для прямоугольника, представляющего всю строку, а не текст, который вы хотите. ИспользованиеsetLocation
в пользовательском наборщике работает, но это смещает соответствующий текстовый рейнджер, так что он может перекрываться с другим текстом. Пользовательский NSTextAttachment в моем случае не подходит, так как мне нужно, чтобы пользователь мог редактировать символы текста токена по отдельности. - person Noah Gilmore   schedule 26.09.2019