我有一个包含较长段落的文本视图。我不想让用户滚动以继续阅读,而是希望将文本分成页面。
屏幕将占用全部文字,然后用户可以单击下一页或上一页。换句话说,市场上任何电子阅读器的行为。
我真的不确定从哪里开始。我会假设我需要做的几件事:
let count = str.count
let userWidth = UIScreen.main.bounds.size.width
let userHeight = UIScreen.main.bounds.size.height
但是,我无法提出任何可行的方法,即使这似乎也不是正确的方法。
关于如何开始创建电子阅读器翻页功能的任何建议?如果可以简化操作,我可以使用UIWebView代替UITextView。
谢谢!
答案 0 :(得分:2)
您的方向正确,但是您的实现仅适用于等宽字体(Menlo,Courier等),因为比例字体(Helvetica,Times等)的字母宽度因字母而异。另外,您的计划中文字的中间会打断,这可能不是最佳选择。
TextKit提供了一些工具,可以使您更轻松地进行所有操作。如果要进行标准分页,而不是在单词边界处换行,可以使用NSLayoutManager来完成。
一些注意事项:
您不能使用屏幕宽度来准确计算视图的大小,因为您需要考虑安全区域和UITextView的textContainerInset。
我将分页给你。您可以通过从字符串中修剪前一页来计算页面的上一页,或者简单地在范围内前后移动。
func stringThatFitsOnScreen(originalString: String) -> String? {
// the visible rect area the text will fit into
let userWidth = textView.bounds.size.width - textView.textContainerInset.right - textView.textContainerInset.left
let userHeight = textView.bounds.size.height - textView.textContainerInset.top - textView.textContainerInset.bottom
let rect = CGRect(x: 0, y: 0, width: userWidth, height: userHeight)
// we need a new UITextView object to calculate the glyphRange. This is in addition to
// the UITextView that actually shows the text (probably a IBOutlet)
let tempTextView = UITextView(frame: self.textView.bounds)
tempTextView.font = textView.font
tempTextView.text = originalString
// get the layout manager and use it to layout the text
let layoutManager = tempTextView.layoutManager
layoutManager.ensureLayout(for: tempTextView.textContainer)
// get the range of text that fits in visible rect
let rangeThatFits = layoutManager.glyphRange(forBoundingRect: rect, in: tempTextView.textContainer)
// convert from NSRange to Range
guard let stringRange = Range(rangeThatFits, in: originalString) else {
return nil
}
// return the text that fits
let subString = originalString[stringRange]
return String(subString)
}
有更复杂的方法来混合和匹配文本视图,布局管理器和文本容器。只要掌握了简单的知识,就可以对其进行调查。