【问题标题】:NSAttributedString inserting a bullet point?NSAttributedString 插入一个项目符号?
【发布时间】:2011-10-02 10:29:23
【问题描述】:

所以我有一个NSAttributedString 我想在一段文本的开头插入一个bullet point。我怎样才能做到这一点?如何创建一个CTPAragraphStyle,在我显示文本时创建此项目符号?

编辑: 应该在 iOS

上可用

【问题讨论】:

    标签: ios objective-c swift nsattributedstring bulletedlist


    【解决方案1】:

    这是 Krunal 在 Objective-C 中的出色答案。它还删除了最后一个项目符号上的段落间距,以避免 UILabel 上的额外底部填充。

    UILabel *label = [UILabel new];
    label.frame = CGRectMake(40, 100, 280, 600);
    label.textColor = UIColor.lightGrayColor;
    label.numberOfLines = 0;
    
    NSArray *stringArray = @[@"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                             @"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
                             @"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
                             @"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
                             ];
    
    label.attributedText = [self attributedStringForBulletTexts:stringArray
                                                       withFont:label.font
                                                   bulletString:@""
                                                    indentation:20
                                                    lineSpacing:2
                                               paragraphSpacing:12
                                                      textColor:UIColor.grayColor
                                                    bulletColor:UIColor.greenColor];
    

    这里是创建实际属性文本的函数:

    - (NSAttributedString *)attributedStringForBulletTexts:(NSArray *)stringList
                                                  withFont:(UIFont *)font
                                              bulletString:(NSString *)bullet
                                               indentation:(CGFloat)indentation
                                               lineSpacing:(CGFloat)lineSpacing
                                          paragraphSpacing:(CGFloat)paragraphSpacing
                                                 textColor:(UIColor *)textColor
                                               bulletColor:(UIColor *)bulletColor {
    
        NSDictionary *textAttributes = @{NSFontAttributeName: font,
                                     NSForegroundColorAttributeName: textColor};
        NSDictionary *bulletAttributes = @{NSFontAttributeName: font, NSForegroundColorAttributeName: bulletColor};
    
        NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
        paragraphStyle.tabStops = @[[[NSTextTab alloc] initWithTextAlignment: NSTextAlignmentLeft location:indentation options:@{}]];
        paragraphStyle.defaultTabInterval = indentation;
        paragraphStyle.lineSpacing = lineSpacing;
        paragraphStyle.paragraphSpacing = paragraphSpacing;
        paragraphStyle.headIndent = indentation;
    
        NSMutableAttributedString *bulletList = [NSMutableAttributedString new];
    
        for (NSString *string in stringList) {
            NSString *formattedString = [NSString stringWithFormat:@"%@\t%@\n", bullet, string];
            NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:formattedString];
            if ([string isEqualToString: stringList.lastObject]) {
                paragraphStyle = [paragraphStyle mutableCopy];
                paragraphStyle.paragraphSpacing = 0;
            }
            [attributedString addAttributes:@{NSParagraphStyleAttributeName: paragraphStyle} range:NSMakeRange(0, attributedString.length)];
            [attributedString addAttributes:textAttributes range:NSMakeRange(0, attributedString.length)];
    
            NSRange rangeForBullet = [formattedString rangeOfString:bullet];
            [attributedString addAttributes:bulletAttributes range:rangeForBullet];
            [bulletList appendAttributedString:attributedString];
        }
    
        return bulletList;
    }
    

    【讨论】:

      【解决方案2】:

      这是一个很好的 Swift 解决方案

      let label = UILabel()
      label.frame = CGRect(x: 40, y: 100, width: 280, height: 600)
      label.textColor = UIColor.lightGray
      label.numberOfLines = 0
      
      let arrayString = [
          "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
          "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
          "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
          "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
      ]
      
      label.attributedText = add(stringList: arrayString, font: label.font, bullet: "")
      
      self.view.addSubview(label)
      

      添加项目符号属性

      斯威夫特 4.2++

      func add(stringList: [String],
               font: UIFont,
               bullet: String = "\u{2022}",
               indentation: CGFloat = 20,
               lineSpacing: CGFloat = 2,
               paragraphSpacing: CGFloat = 12,
               textColor: UIColor = .gray,
               bulletColor: UIColor = .green) -> NSAttributedString {
      
          let textAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: textColor]
          let bulletAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: bulletColor]
      
          let paragraphStyle = NSMutableParagraphStyle()
          let nonOptions = [NSTextTab.OptionKey: Any]()
          paragraphStyle.tabStops = [
              NSTextTab(textAlignment: .left, location: indentation, options: nonOptions)]
          paragraphStyle.defaultTabInterval = indentation
          //paragraphStyle.firstLineHeadIndent = 0
          //paragraphStyle.headIndent = 20
          //paragraphStyle.tailIndent = 1
          paragraphStyle.lineSpacing = lineSpacing
          paragraphStyle.paragraphSpacing = paragraphSpacing
          paragraphStyle.headIndent = indentation
      
          let bulletList = NSMutableAttributedString()
          for string in stringList {
              let formattedString = "\(bullet)\t\(string)\n"
              let attributedString = NSMutableAttributedString(string: formattedString)
      
              attributedString.addAttributes(
                  [NSAttributedString.Key.paragraphStyle : paragraphStyle],
                  range: NSMakeRange(0, attributedString.length))
      
              attributedString.addAttributes(
                  textAttributes,
                  range: NSMakeRange(0, attributedString.length))
      
              let string:NSString = NSString(string: formattedString)
              let rangeForBullet:NSRange = string.range(of: bullet)
              attributedString.addAttributes(bulletAttributes, range: rangeForBullet)
              bulletList.append(attributedString)
          }
      
          return bulletList
      }
      

      斯威夫特 4.0 和 4.1

      func add(stringList: [String],
               font: UIFont,
               bullet: String = "\u{2022}",
               indentation: CGFloat = 20,
               lineSpacing: CGFloat = 2,
               paragraphSpacing: CGFloat = 12,
               textColor: UIColor = .gray,
               bulletColor: UIColor = .green) -> NSAttributedString {
      
          let textAttributes: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: font, NSAttributedStringKey.foregroundColor: textColor]
          let bulletAttributes: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: font, NSAttributedStringKey.foregroundColor: bulletColor]
      
          let paragraphStyle = NSMutableParagraphStyle()
          let nonOptions = [NSTextTab.OptionKey: Any]()
          paragraphStyle.tabStops = [
              NSTextTab(textAlignment: .left, location: indentation, options: nonOptions)]
          paragraphStyle.defaultTabInterval = indentation
          //paragraphStyle.firstLineHeadIndent = 0
          //paragraphStyle.headIndent = 20
          //paragraphStyle.tailIndent = 1
          paragraphStyle.lineSpacing = lineSpacing
          paragraphStyle.paragraphSpacing = paragraphSpacing
          paragraphStyle.headIndent = indentation
      
          let bulletList = NSMutableAttributedString()
          for string in stringList {
              let formattedString = "\(bullet)\t\(string)\n"
              let attributedString = NSMutableAttributedString(string: formattedString)
      
              attributedString.addAttributes(
                  [NSAttributedStringKey.paragraphStyle : paragraphStyle],
                  range: NSMakeRange(0, attributedString.length))
      
              attributedString.addAttributes(
                  textAttributes,
                  range: NSMakeRange(0, attributedString.length))
      
              let string:NSString = NSString(string: formattedString)
              let rangeForBullet:NSRange = string.range(of: bullet)
              attributedString.addAttributes(bulletAttributes, range: rangeForBullet)
              bulletList.append(attributedString)
          }
      
          return bulletList
      }
      

      结果如下:

      【讨论】:

      • 这样一个很好的答案,但如果字符串包含新行(“\n”),缩进被破坏。我该如何处理这种情况
      【解决方案3】:

      这是一种适用于 iOS6 的更现代的方法:

      NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:@"•\texample bullet fill out the text to check what happens on the second line and make sure it is lining up OK"];
      
      NSMutableParagraphStyle *paragraphStyle;
      paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
      [paragraphStyle setTabStops:@[[[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:15 options:nil]]];
      [paragraphStyle setDefaultTabInterval:15];
      [paragraphStyle setFirstLineHeadIndent:0];
      [paragraphStyle setHeadIndent:15];
      
      [string addAttributes:@{NSParagraphStyleAttributeName: paragraphStyle} range:NSMakeRange(0,[string length])];
      

      【讨论】:

      • 太棒了,非常感谢。确认在 iOS 9.3 上工作。
      【解决方案4】:

      不是这个问题的实际答案,但这可以提供帮助。

      只需添加“•”

      即使我正在为我的 textView 寻找类似的东西。我所做的,只需在上面的字符串中附加我的字符​​串并将其传递给我的 textView,标签也可以这样做。我为未来的观众回答了这个问题。

      【讨论】:

      • 嗯,我想知道当你增加字体时是否会正确调整大小
      • 是的。它会增加大小,因为它只是一个字母。如果您认为这是一种很酷的方式,请点赞。
      【解决方案5】:

      简单一点:[mutableAttributedString insertAttributedString:@"•\t" atIndex:0];

      难点。大致如下。 (这是从一个更大的项目中提取的,但它可能会给你一个不错的开始。)

      NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:@"•\texample bullet fill out the text to check what happens on the second line and make sure it is lining up OK"];
      
      CTTextAlignment alignment = kCTLeftTextAlignment;
      CGFloat paragraphSpacing = 0.0;
      CGFloat paragraphSpacingBefore = 0.0;
      CGFloat firstLineHeadIndent = 15.0;
      CGFloat headIndent = 30.0;
      
      CGFloat firstTabStop = 15.0; // width of your indent
      CGFloat lineSpacing = 0.45;
      
      CTTextTabRef tabArray[] = { CTTextTabCreate(0, firstTabStop, NULL) };
      
      CFArrayRef tabStops = CFArrayCreate( kCFAllocatorDefault, (const void**) tabArray, 1, &kCFTypeArrayCallBacks );
      CFRelease(tabArray[0]);
      
      CTParagraphStyleSetting altSettings[] = 
      {
          { kCTParagraphStyleSpecifierLineSpacing, sizeof(CGFloat), &lineSpacing},
          { kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment), &alignment},
          { kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), &firstLineHeadIndent},
          { kCTParagraphStyleSpecifierHeadIndent, sizeof(CGFloat), &headIndent},
          { kCTParagraphStyleSpecifierTabStops, sizeof(CFArrayRef), &tabStops},
          { kCTParagraphStyleSpecifierParagraphSpacing, sizeof(CGFloat), &paragraphSpacing},
          { kCTParagraphStyleSpecifierParagraphSpacingBefore, sizeof(CGFloat), &paragraphSpacingBefore}
      }; 
      
      CTParagraphStyleRef style;
      style = CTParagraphStyleCreate( altSettings, sizeof(altSettings) / sizeof(CTParagraphStyleSetting) );
      
      if ( style == NULL )
      {
          NSLog(@"*** Unable To Create CTParagraphStyle in apply paragraph formatting" );
          return;
      }
      
      [string addAttributes:[NSDictionary dictionaryWithObjectsAndKeys:(NSObject*)style,(NSString*) kCTParagraphStyleAttributeName, nil] range:NSMakeRange(0,[string length])];
      
      CFRelease(tabStops);
      CFRelease(style);
      

      你需要包含CoreText框架,然后导入CoreText/CoreText.h

      【讨论】:

      • 这是在 iOS 中设置段落样式的首选示例,但我会警告不要释放 tabStopsstyle,直到使用它们的属性字符串被释放。在我的项目中,我必须对所有拥有的样式组件进行属性化,以防止获得 EXC_BAD_ACCESS。
      【解决方案6】:

      您不会在 iOS 中实现带有段落样式的项目符号列表。根据需要设置制表位,然后在段落开头插入制表符、项目符号、制表符。

      CTParagraphStyle 非常不灵活,因此您不能只添加您选择的新样式。但是,您可以将您喜欢的任何属性 (MYBulletStyle) 添加到 NSAttributedString 中的任意运行。这对于通过NSAttributedString 传递项目符号列表信息非常有用,然后在您准备好显示项目符号时重新构建字符串以包含项目符号。但 Core Text 不会自动为您呈现项目符号。

      【讨论】:

      • 我知道这篇文章已经很老了,但是你介意提供一些示例吗?当您希望除项目符号之外的整个段落缩进时,制表位如何解决问题?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      • 2012-01-04
      • 1970-01-01
      相关资源
      最近更新 更多