gpt4 book ai didi

ios - 多行文本的 LayoutManager boundingRectForGlyphRange

转载 作者:行者123 更新时间:2023-11-29 10:36:29 28 4
gpt4 key购买 nike

我有一段文字,它在屏幕上的显示完全像这样:

#first SomePersonFirstName
SomePersonLastName #secondTag

在我的应用程序中,我保留了有关此文本的 3 个标签及其范围的信息,它们是:

  1. #第一
  2. SomePersonFirstName SomePersonLastName
  3. #secondTag

现在,在我将它显示给用户后,我想检测点击了哪个,因此我遍历了我拥有的所有信息,为每个信息获取一个 boundingRectForGlyphRange,并检查此 rect 是否包含单击它的位置。

一切正常,但我遇到了一个奇怪的情况,这打破了我对如何做的想法。问题是这些标签的边界矩形重叠。

enter image description here

因为 person 标签被分成两行,绑定(bind)矩形从 0,0 开始并覆盖#first 边界矩形。

问题是,当您点击这个冲突区域时,无法确定点击了哪一个。

我实际上不知道如何处理它。有没有其他方法可以检测边界矩形,但实际上不会绑定(bind)到空白区域,只会覆盖文本本身?

编辑

我使用的代码:

- (CGRect)boundingRectForCharacterRange:(NSRange)range
{
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:self.labelTitle.attributedText];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(self.labelTitle.bounds.size.width, CGFLOAT_MAX)];
textContainer.lineFragmentPadding = 0;
textContainer.lineBreakMode = self.labelTitle.lineBreakMode;
[layoutManager addTextContainer:textContainer];

NSRange glyphRange;
[layoutManager characterRangeForGlyphRange:range actualGlyphRange:&glyphRange];
return [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
}

-(void)tapped:(UIGestureRecognizer *)recognizer
{
UILabel *label = (UILabel *)recognizer.view;
CGPoint location = [recognizer locationInView:label];

CommentTag* selectedCommentTag = nil;
for (CommentTag* commentTag in self.comment.tags)
{
CGRect commentRect = [self boundingRectForCharacterRange:[commentTag tagRange]];
if(CGRectContainsPoint(commentRect, location))
{
if(selectedCommentTag == nil)
{
selectedCommentTag = commentTag;
}
else
{
if(selectedCommentTag.offset > commentTag.offset)
{
selectedCommentTag = commentTag;
}
}
}
}

if(selectedCommentTag)
{
if([selectedCommentTag.type isEqualToString:COMMENTTAG_TYPE_TAG])
{
NSLog(@"%@", [selectedCommentTag value]);
}
}
}

这里我只取左边的第一个标签,但这并没有解决我示例中的#secondTag 问题

最佳答案

两个边界矩形可以重叠的情况有两(三)种:

  1. 这两个范围与索引值重叠。
  2. 其中一个边界矩形占据多行。
  3. 两个边界矩形都占据多行。

对于 (1),您只需制定自己的一套规则来接受对常见字形的点击。

对于 (2),总是更喜欢触摸仅跨越一行的范围——您可以通过比较矩形高度来判断这一点。

对于 (3),您必须遍历这些行。

或者,你考虑过相反的方法吗?

NSRange characterRange = [layoutManager glyphRangeForBoundingRect:CGRectMake(point.x, point.y, 1, 1) inTextContainer:container];
if (NSLocationInRange(characterRange.location, firstRange) {
// ...
} else if (NSLocationInRange(characterRange.location, secondRange) {
// ...
} // etc...

通过将您的触摸点转换为大小为 1x1CGRect,您可以让 layoutManager 为您提供 NSRange 的长度 1 表示您触摸点的单个字形。使用此 NSRangelocation,您可以与您的 NSRange 列表进行比较,看看您命中了哪一个。使用您的来源:

- (NSUInteger)glyphIndexForPoint:(CGPoint)point
{
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:self.labelTitle.attributedText];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(self.labelTitle.bounds.size.width, CGFLOAT_MAX)];
textContainer.lineFragmentPadding = 0;
textContainer.lineBreakMode = self.labelTitle.lineBreakMode;
[layoutManager addTextContainer:textContainer];
return [layoutManager glyphIndexForPoint:point inTextContainer:textContainer];;
}

-(void)tapped:(UIGestureRecognizer *)recognizer
{
UILabel *label = (UILabel *)recognizer.view;
CGPoint location = [recognizer locationInView:label];
NSUInteger glyphIndex = [self glyphIndexForPoint:location];

CommentTag* selectedCommentTag = nil;
for (CommentTag* commentTag in self.comment.tags)
{
if (NSLocationInRange(glyphIndex, [commentTag tagRange]))
{
NSLog(@"%@", commentTag); //selected tag
break
}
}
}

关于ios - 多行文本的 LayoutManager boundingRectForGlyphRange,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26675439/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com