CGRect用于多行文本的选定UITextRange调整?

bra*_*ipt 13 objective-c uitextview nsattributedstring ios

我已经使用这个答案来为特定范围的文本创建CGRect.

在这里UITextView我设置了它attributedText(所以我有一堆带有不同字形大小的样式文本).

这对于左对齐的第一行文本非常有用,但在使用NSTextAlignmentJustified或时使用时会产生一些非常奇怪的结果NSTextAlignmentCenter.

当线条缠绕时它也不能正确计算,或者(如果有\n线条断裂).

我得到这样的东西(这是中心对齐):

在此输入图像描述

相反,我期待这个:

在此输入图像描述

这个有一个\n换行符 - 前两个代码位被成功突出显示,但最后一个more code for you to see不是因为文本换行没有考虑到x,y计算中.

这是我的实现:

- (void)formatMarkdownCodeBlockWithAttributes:(NSDictionary *)attributesDict
                      withHighlightProperties:(NSDictionary *)highlightProperties
                               forFontSize:(CGFloat)pointSize
{
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"`.+?`" options:NO error:nil];
    NSArray *matchesArray = [regex matchesInString:[self.attributedString string] options:NO range:NSMakeRange(0, self.attributedString.length)];
    for (NSTextCheckingResult *match in matchesArray)
    {
        NSRange range = [match range];
        if (range.location != NSNotFound) {

            self.textView.attributedText = self.attributedString;

            CGRect codeRect = [self frameOfTextRange:range forString:[[self.attributedString string] substringWithRange:range] forFontSize:pointSize];
            UIView *highlightView = [[UIView alloc] initWithFrame:codeRect];
            highlightView.layer.cornerRadius = 4;
            highlightView.layer.borderWidth = 1;
            highlightView.backgroundColor = [highlightProperties valueForKey:@"backgroundColor"];
            highlightView.layer.borderColor = [[highlightProperties valueForKey:@"borderColor"] CGColor];
            [self.contentView insertSubview:highlightView atIndex:0];

            [self.attributedString addAttributes:attributesDict range:range];

            //strip first and last `
            [[self.attributedString mutableString] replaceOccurrencesOfString:@"(^`|`$)" withString:@" " options:NSRegularExpressionSearch range:range];
        }
    }
}

- (CGRect)frameOfTextRange:(NSRange)range forString:(NSString *)string forFontSize:(CGFloat)pointSize
{
    self.textView.selectedRange = range;
    UITextRange *textRange = [self.textView selectedTextRange];
    CGRect rect = [self.textView firstRectForRange:textRange];
    //These three lines are a workaround for getting the correct width of the string since I'm always using the monospaced Menlo font.
    rect.size.width = ((pointSize / 1.65) * string.length) - 4;
    rect.origin.x+=2;
    rect.origin.y+=2;
    return rect;
}
Run Code Online (Sandbox Code Playgroud)

哦,如果你想要它,这里是我正在玩的字符串:

*This* is **awesome** @mention `code` more \n `code and code` #hashtag [markdown](http://google.com) __and__ @mention2 {#FFFFFF|colored text} This**will also** work but ** will not ** **work** Also, some `more code for you to see`
Run Code Online (Sandbox Code Playgroud)

注意:请不要建议我使用TTTAttributedLabelOHAttributedLabel.

Avt*_*Avt 4

我认为你所有的问题都是由于指令顺序不正确造成的。

你必须

  1. 设置文本对齐方式
  2. 查找所需的子字符串并向其添加特定属性
  3. 然后才用子视图突出显示字符串。

此外,在这种情况下,您不需要使用“获取字符串正确宽度的解决方法,因为我总是使用等宽 Menlo 字体”。

我稍微简化了您的代码以使其更容易理解。

结果: 在此输入图像描述

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSDictionary *basicAttributes = @{ NSFontAttributeName : [UIFont boldSystemFontOfSize:18],
                                       NSForegroundColorAttributeName : [UIColor blackColor] };
    NSDictionary *attributes = @{ NSFontAttributeName : [UIFont systemFontOfSize:15],
                                  NSForegroundColorAttributeName : [UIColor darkGrayColor]};


    _textView.attributedText = [[NSAttributedString alloc] initWithString:
                                @"*This* is **awesome** @mention `code` more \n `code and code` #hashtag [markdown](http://google.com) __and__ @mention2 {#FFFFFF|colored text} This**will also** work but ** will not ** **work** Also, some `more code for you to see`" attributes:attributes];
    _textView.textAlignment = NSTextAlignmentCenter;

    [self formatMarkdownCodeBlockWithAttributes:basicAttributes];
}

- (void)formatMarkdownCodeBlockWithAttributes:(NSDictionary *)attributesDict
{
    NSMutableString *theString = [_textView.attributedText.string mutableCopy];
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"`.+?`" options:NO error:nil];
    NSArray *matchesArray = [regex matchesInString:theString options:NO range:NSMakeRange(0, theString.length)];

    NSMutableAttributedString *theAttributedString = [_textView.attributedText mutableCopy];
    for (NSTextCheckingResult *match in matchesArray)
    {
        NSRange range = [match range];
        if (range.location != NSNotFound) {
            [theAttributedString addAttributes:attributesDict range:range];
        }
    }

    _textView.attributedText = theAttributedString;

    for (NSTextCheckingResult *match in matchesArray)
    {
        NSRange range = [match range];
        if (range.location != NSNotFound) {

            CGRect codeRect = [self frameOfTextRange:range];
            UIView *highlightView = [[UIView alloc] initWithFrame:codeRect];
            highlightView.layer.cornerRadius = 4;
            highlightView.layer.borderWidth = 1;
            highlightView.backgroundColor = [UIColor yellowColor];
            highlightView.layer.borderColor = [[UIColor redColor] CGColor];
            [_textView insertSubview:highlightView atIndex:0];
        }
    }
}

- (CGRect)frameOfTextRange:(NSRange)range
{
    self.textView.selectedRange = range;
    UITextRange *textRange = [self.textView selectedTextRange];
    CGRect rect = [self.textView firstRectForRange:textRange];
    return rect;
}
Run Code Online (Sandbox Code Playgroud)