我想让一个NSAttributedString包含多个消息。如果单个消息具有较长的文本并且可以环绕,则我希望行距为5。因为我有一个NSAttributedString包含多个消息,所以我希望每个消息之间都有较大的行距。假设20

我想要的是

ios - 如何为NSAttributedString的不同部分添加不同的行距?-LMLPHP

“我看到”是一条消息。 “我认为这两者都将...”是一条消息,尽管它可以分为两行,而“像单向聊天”是一条消息。

请注意,第二和第三之间的行距如何小于第一和第二以及第三和第四行之间的行距。

我尝试过的

我在每个消息的末尾附加一个\ n,并且我尝试使用NSParagraphStyle来控制行距,但似乎全无。

        // index is the index of the group of messages as I iterate through them
        // contentText is an NSMutableAttributedString
        if index != messages.count - 1 {
            let style = NSMutableParagraphStyle()
            style.lineSpacing = 40.0

            let lineReturn = NSMutableAttributedString(string: "\n")
            contentText.appendAttributedString(lineReturn)

            if index == 0 {
                contentText.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSMakeRange(contentText.length-lineReturn.length, lineReturn.length))
            } else {
                contentText.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSMakeRange(contentText.length-lineReturn.length-1, lineReturn.length+1))
            }
        }

如果我将行距添加到开头,它将设置整个标签的行距。
        if index == 0 {
            let style = NSMutableParagraphStyle()
            style.lineSpacing = 40.0
            contentText.addAttribute(NSParagraphStyleAttributeName, value: style1, range: NSMakeRange(start, 1))
        }

(这实际上只是我的最新尝试。)

谢谢你的帮助! :)

最佳答案

详细信息

  • 您的英文邮件中有非常基本的自定义标记,因此您可以
    解析出不同的片段
  • 指示翻译人员将标记保留在其中并翻译
    rest有一个UIView可以用作此消息的容器
  • 分解您的英语信息,以分隔常规文本
    从可点击的文字
  • 为每个片段在容器UIView上创建一个UILabel
  • 对于可点击的作品,设置样式,允许用户交互
    并创建您的点击手势识别器
  • 做一些非常基本的簿记工作,以使单词完美地对接
    线

    为了了解。

  • 我在视图控制器的viewDidLoad中放置了这个:
    [self buildAgreeTextViewFromString:NSLocalizedString(@"I agree to the #<ts>terms of service# and #<pp>privacy policy#",
    
    
                                                     @"PLEASE NOTE: please translate \"terms of service\" and \"privacy policy\" as well, and leave the #<ts># and #<pp># around your translations just as in the English version of this message.")];
    

    我正在调用将构建消息的方法。注意我想出的标记。您当然可以自己发明,但关键是我还要标记每个可点击区域的末端,因为它们跨越了多个单词。

    这是将消息组合在一起的方法-参见下文。首先,我将英文消息分解为#字符(或@“#”字符串)。这样,我得到了需要分别为其创建标签的每个部件。我遍历它们,并寻找我的<ts><pp>的基本标记,以检测哪些片段是指向什么的链接。如果我正在使用的文本块是一个链接,那么我会设置一些样式并为其设置点击手势识别器。我当然也删除了标记字符。我认为这是一种非常简单的方法。

    请注意一些细微之处,例如如何处理空格:我只是从(本地化)字符串中提取空格。如果没有空格(中文,日文),那么块之间也将没有空格。如果有空格,则那些空格会根据需要自动隔开(例如,英语)。但是,当我不得不在下一行的开头放置一个单词时,我确实需要确保从该文本中删除任何空白前缀,因为否则它无法正确对齐。
    - (void)buildAgreeTextViewFromString:(NSString *)localizedString
    {
      // 1. Split the localized string on the # sign:
      NSArray *localizedStringPieces = [localizedString componentsSeparatedByString:@"#"];
    
      // 2. Loop through all the pieces:
      NSUInteger msgChunkCount = localizedStringPieces ? localizedStringPieces.count : 0;
      CGPoint wordLocation = CGPointMake(0.0, 0.0);
      for (NSUInteger i = 0; i < msgChunkCount; i++)
      {
        NSString *chunk = [localizedStringPieces objectAtIndex:i];
        if ([chunk isEqualToString:@""])
        {
          continue;     // skip this loop if the chunk is empty
        }
    
        // 3. Determine what type of word this is:
        BOOL isTermsOfServiceLink = [chunk hasPrefix:@"<ts>"];
        BOOL isPrivacyPolicyLink  = [chunk hasPrefix:@"<pp>"];
        BOOL isLink = (BOOL)(isTermsOfServiceLink || isPrivacyPolicyLink);
    
        // 4. Create label, styling dependent on whether it's a link:
        UILabel *label = [[UILabel alloc] init];
        label.font = [UIFont systemFontOfSize:15.0f];
        label.text = chunk;
        label.userInteractionEnabled = isLink;
    
        if (isLink)
        {
          label.textColor = [UIColor colorWithRed:110/255.0f green:181/255.0f blue:229/255.0f alpha:1.0];
          label.highlightedTextColor = [UIColor yellowColor];
    
          // 5. Set tap gesture for this clickable text:
          SEL selectorAction = isTermsOfServiceLink ? @selector(tapOnTermsOfServiceLink:) : @selector(tapOnPrivacyPolicyLink:);
          UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                       action:selectorAction];
          [label addGestureRecognizer:tapGesture];
    
          // Trim the markup characters from the label:
          if (isTermsOfServiceLink)
            label.text = [label.text stringByReplacingOccurrencesOfString:@"<ts>" withString:@""];
          if (isPrivacyPolicyLink)
            label.text = [label.text stringByReplacingOccurrencesOfString:@"<pp>" withString:@""];
        }
        else
        {
          label.textColor = [UIColor whiteColor];
        }
    
        // 6. Lay out the labels so it forms a complete sentence again:
    
        // If this word doesn't fit at end of this line, then move it to the next
        // line and make sure any leading spaces are stripped off so it aligns nicely:
    
        [label sizeToFit];
    
        if (self.agreeTextContainerView.frame.size.width < wordLocation.x + label.bounds.size.width)
        {
          wordLocation.x = 0.0;                       // move this word all the way to the left...
          wordLocation.y += label.frame.size.height;  // ...on the next line
    
          // And trim of any leading white space:
          NSRange startingWhiteSpaceRange = [label.text rangeOfString:@"^\\s*"
                                                              options:NSRegularExpressionSearch];
          if (startingWhiteSpaceRange.location == 0)
          {
            label.text = [label.text stringByReplacingCharactersInRange:startingWhiteSpaceRange
                                                             withString:@""];
            [label sizeToFit];
          }
        }
    
        // Set the location for this label:
        label.frame = CGRectMake(wordLocation.x,
                                 wordLocation.y,
                                 label.frame.size.width,
                                 label.frame.size.height);
        // Show this label:
        [self.agreeTextContainerView addSubview:label];
    
        // Update the horizontal position for the next word:
        wordLocation.x += label.frame.size.width;
      }
    }
    

    如果要使用手势,请使用此方法。
    - (void)tapOnTermsOfServiceLink:(UITapGestureRecognizer *)tapGesture
    {
      if (tapGesture.state == UIGestureRecognizerStateEnded)
      {
        NSLog(@"User tapped on the Terms of Service link");
      }
    }
    
    
    - (void)tapOnPrivacyPolicyLink:(UITapGestureRecognizer *)tapGesture
    {
      if (tapGesture.state == UIGestureRecognizerStateEnded)
      {
        NSLog(@"User tapped on the Privacy Policy link");
      }
    }
    

    希望这可以帮助。我敢肯定有很多更聪明,更优雅的方法可以做到这一点,但这就是我能想到的,并且效果很好。

    此答案显示如下屏幕截图所示的输出...但是您从此答案中获得了灵感。

    ios - 如何为NSAttributedString的不同部分添加不同的行距?-LMLPHP

    10-08 16:26