如何使用 PDFKit 获取段落的高度
How to get the height of a paragraph using PDFKit
我正在使用 iOS PDFKit 编写 pdf。通常,我可以通过执行以下操作来获取单个文本项(例如标题)的高度:
return titleStringRect.origin.y + titleStringRect.size.height
其中 titleStringRect 是包含字符串的 CGRect。 returned 值是该文本底部的 y-coordinate,这样我就知道从哪里开始写下一行文本。
我还没有找到一种方法来知道段落在哪里结束。我找到的解决方案是只制作一个足够大的 CGRect 以确保该段落完全适合。
我需要确切地知道 CGRect 的高度应该基于将写入其中的字符串。这是我的代码:
func addParagraph(pageRect: CGRect, textTop: CGFloat, text: String) {
let textFont = UIFont(name: "Helvetica", size: 12)
let backupFont = UIFont.systemFont(ofSize: 12, weight: .regular)
// Set paragraph information. (wraps at word breaks)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .natural
paragraphStyle.lineBreakMode = .byWordWrapping
// Set the text attributes
let textAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: textFont ?? backupFont
]
let attributedText = NSAttributedString(
string: text,
attributes: textAttributes
)
let textRect = CGRect(
x: 50.0,
y: textTop,
width: pageRect.width - 100,
height: pageRect.height - textTop - pageRect.height / 5.0
)
attributedText.draw(in: textRect)
}
如您所见,无论该段落实际有多少行,上面的代码只生成一个 CGRect,它是前一个文本下方 space 的 1/5。
我试过平均每行的字符数以估计该段落将有多少行,但这是不可靠的,而且绝对是一个 hack。
我需要的是将 addParagraph 函数 return 设为段落底部的 y-coordinate 以便我知道从哪里开始编写下一段内容。
我最终找到了解决方案,而且非常简单。我会 post 代码,然后向遇到此问题的其他人解释它。
let paragraphSize = CGSize(width: pageRect.width - 100, height: pageRect.height)
let paragraphRect = attributedText.boundingRect(with: paragraphSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil)
首先定义一个一定宽高的CGSize。将宽度设置为您希望段落的宽度,并将高度设置为适合内容的较大值。然后调用
attributedText.boundingRect(with: paragraphSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil)
其中 attributedText 是段落内容。 boundingRect 方法 return 是一个 CGRect,它是适合内容所需的大小,但仅此而已。现在您可以 return 段落底部。此方法不会更改宽度,除非它无法使字符串适合您提供的高度。就我的目的而言,这是完美的。这是完整的代码:
func addParagraph(pageRect: CGRect, textTop: CGFloat, paragraphText: String) -> CGFloat {
let textFont = UIFont(name: "Helvetica", size: 12)
let backupFont = UIFont.systemFont(ofSize: 12, weight: .regular)
// Set paragraph information. (wraps at word breaks)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .natural
paragraphStyle.lineBreakMode = .byWordWrapping
// Set the text attributes
let textAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: textFont ?? backupFont
]
let attributedText = NSAttributedString(
string: paragraphText,
attributes: textAttributes
)
// determine the size of CGRect needed for the string that was given by caller
let paragraphSize = CGSize(width: pageRect.width - 100, height: pageRect.height)
let paragraphRect = attributedText.boundingRect(with: paragraphSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil)
// Create a CGRect that is the same size as paragraphRect but positioned on the pdf where we want to draw the paragraph
let positionedParagraphRect = CGRect(
x: 50,
y: textTop,
width: paragraphRect.width,
height: paragraphRect.height
)
// draw the paragraph into that CGRect
attributedText.draw(in: positionedParagraphRect)
// return the bottom of the paragraph
return positionedParagraphRect.origin.y + positionedParagraphRect.size.height
}
我正在使用 iOS PDFKit 编写 pdf。通常,我可以通过执行以下操作来获取单个文本项(例如标题)的高度:
return titleStringRect.origin.y + titleStringRect.size.height
其中 titleStringRect 是包含字符串的 CGRect。 returned 值是该文本底部的 y-coordinate,这样我就知道从哪里开始写下一行文本。 我还没有找到一种方法来知道段落在哪里结束。我找到的解决方案是只制作一个足够大的 CGRect 以确保该段落完全适合。 我需要确切地知道 CGRect 的高度应该基于将写入其中的字符串。这是我的代码:
func addParagraph(pageRect: CGRect, textTop: CGFloat, text: String) {
let textFont = UIFont(name: "Helvetica", size: 12)
let backupFont = UIFont.systemFont(ofSize: 12, weight: .regular)
// Set paragraph information. (wraps at word breaks)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .natural
paragraphStyle.lineBreakMode = .byWordWrapping
// Set the text attributes
let textAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: textFont ?? backupFont
]
let attributedText = NSAttributedString(
string: text,
attributes: textAttributes
)
let textRect = CGRect(
x: 50.0,
y: textTop,
width: pageRect.width - 100,
height: pageRect.height - textTop - pageRect.height / 5.0
)
attributedText.draw(in: textRect)
}
如您所见,无论该段落实际有多少行,上面的代码只生成一个 CGRect,它是前一个文本下方 space 的 1/5。 我试过平均每行的字符数以估计该段落将有多少行,但这是不可靠的,而且绝对是一个 hack。 我需要的是将 addParagraph 函数 return 设为段落底部的 y-coordinate 以便我知道从哪里开始编写下一段内容。
我最终找到了解决方案,而且非常简单。我会 post 代码,然后向遇到此问题的其他人解释它。
let paragraphSize = CGSize(width: pageRect.width - 100, height: pageRect.height)
let paragraphRect = attributedText.boundingRect(with: paragraphSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil)
首先定义一个一定宽高的CGSize。将宽度设置为您希望段落的宽度,并将高度设置为适合内容的较大值。然后调用
attributedText.boundingRect(with: paragraphSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil)
其中 attributedText 是段落内容。 boundingRect 方法 return 是一个 CGRect,它是适合内容所需的大小,但仅此而已。现在您可以 return 段落底部。此方法不会更改宽度,除非它无法使字符串适合您提供的高度。就我的目的而言,这是完美的。这是完整的代码:
func addParagraph(pageRect: CGRect, textTop: CGFloat, paragraphText: String) -> CGFloat {
let textFont = UIFont(name: "Helvetica", size: 12)
let backupFont = UIFont.systemFont(ofSize: 12, weight: .regular)
// Set paragraph information. (wraps at word breaks)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .natural
paragraphStyle.lineBreakMode = .byWordWrapping
// Set the text attributes
let textAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: textFont ?? backupFont
]
let attributedText = NSAttributedString(
string: paragraphText,
attributes: textAttributes
)
// determine the size of CGRect needed for the string that was given by caller
let paragraphSize = CGSize(width: pageRect.width - 100, height: pageRect.height)
let paragraphRect = attributedText.boundingRect(with: paragraphSize, options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil)
// Create a CGRect that is the same size as paragraphRect but positioned on the pdf where we want to draw the paragraph
let positionedParagraphRect = CGRect(
x: 50,
y: textTop,
width: paragraphRect.width,
height: paragraphRect.height
)
// draw the paragraph into that CGRect
attributedText.draw(in: positionedParagraphRect)
// return the bottom of the paragraph
return positionedParagraphRect.origin.y + positionedParagraphRect.size.height
}