NSAttributedString和html样式(项目符号对齐)

时间:2016-05-25 13:03:20

标签: ios objective-c swift cocoa-touch nsattributedstring

在我的iOS应用程序中,我使用NSAttributedString生成项目符号列表。不幸的是,我正努力让子弹看起来很漂亮。我的第一次尝试是使用常规文本和子弹的unicode字符,基本上使用这样的字符串:

var attributedString = NSMutableAttributedString(
    string: "Here is a list of bullets and a paragraph introducing them, note that this paragraph spans multiple lines\n" +
    "• This is the first bullet\n" +
    "• Here is a second bullet\n" +
    "• And here is a third bullet with a lot of text such that it overflows to the next line"
)

结果如下:

enter image description here

我喜欢子弹看起来如何,但是最后一个子弹中的溢出文本应该与之前的行对齐,我无法弄清楚如何用纯文本实现(没有对上面的段落应用相同的对齐)

我的第二次尝试是通过NSHTMLTextDocumentType在NSAttributedString中使用html,并使用<ul><li>元素生成项目符号。

let content = "Here is a list of bullets and a paragraph introducing them, note that this paragraph spans multiple lines" +
    "<ul>" +
         "<li>This is the first bullet</li>" +
         "<li>Here is a second bullet</li>" +
         "<li>And here is a third bullet with a lot of text such that it overflows to the next line</li>" +
    "</ul>"
var attributedString = try! NSMutableAttributedString(
    data: content,
    options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
    documentAttributes: nil
)

修复了第一个问题,但引入了一个新问题:

enter image description here

子弹现在间隔太远(从左边缘和右边的文本)。我尝试使用典型的html / css技巧来修复对齐(<li style="text-indent: -10px;">),但NSAttributedString似乎忽略了这些样式。

我尝试使用额外的NSMutableParagraphStyle来解决这个问题,但它似乎弊大于利。这是我试过的:

var paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.firstLineHeadIndent = 0
paragraphStyle.headIndent = 20
attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: attributedStringRange)

这就是我得到的:

enter image description here

正如你所看到的,它只会让事情变得更糟,这是我的问题:

  • 它确实抵消了第二行,但我只想要子弹的效果,而不是之前的段落(我想我可以通过减少效果应用的范围来解决这个问题)
  • 我必须猜测/硬编码偏移量,在我的例子中我选择了20,这对于给出当前字体设置的子弹是不够的,这可能会改变
  • 由于某些原因,子弹间距现在更加无法伸展,似乎只是应用了香草NSParagraphStyle而没有做任何事情这样做,我认为没有办法解决这个问题。

我真正想要的是我的子弹间距看起来类似于第一个截图,而第二行的溢出缩进看起来像第二个,而不必硬编码精确的像素位置。你能帮助我吗?

由于

2 个答案:

答案 0 :(得分:7)

我必须在列表中添加自定义样式,这是我最终用于NSAttributedString

中每个项目符号的段落样式

可以更改headIndentfirstLineHeadIndent,但NSTextTab位置应与headIndent

相同
NSMutableParagraphStyle *const bulletParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
bulletParagraphStyle.headIndent = 60;
bulletParagraphStyle.firstLineHeadIndent = 30;
NSTextTab *listTab = [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentNatural location:60 options:@{}];
bulletParagraphStyle.tabStops = @[listTab];

这可以假设您的项目符号点后面有\t(然后是文本)

答案 1 :(得分:0)

使用<table>代替<ul><li>来处理项目符号对齐。 诸如ul{margin:0;padding:0}li{margin-left: 0;}之类的样式将被忽略。

示例:

let html = "<table>" +
            "<tr><td valign=\"top\" style=\"padding-right:16px\">•</td><td valign=\"top\">text 1</td></tr>" +
            "<tr><td valign=\"top\" style=\"padding-right:16px\">•</td><td valign=\"top\">text 2</td></tr>" +
            "</table>"

let attributedString = try! NSAttributedString(data: html.data(using: String.Encoding.utf8)!,
                               options: [.documentType: NSAttributedString.DocumentType.html,
                                         .characterEncoding: String.Encoding.utf8.rawValue,],
                               documentAttributes: nil)