我试图检测用户何时到达文本中的某个点:UITextView中的字符串。我正在使用scrollViewDidEndDragging
,但结果并不理想。当我完成滚动时,我仍然需要进一步滚动以实现它。此外,当文本只有1页长时,从不调用此方法。是否有更好的方法可以知道屏幕最后一行(或任何其他行)何时可见?
谢谢
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let bottomEdge: CGFloat = textField.contentOffset.y + textField.frame.size.height
if (bottomEdge >= scrollView.contentSize.height) {
//do stuff
}
}
答案 0 :(得分:0)
这是一个天真的解决方案,它获取子字符串的rect并检查该rect是否可见。
这个实现的主要缺点是它只有在你的子串是唯一的时才有效(因为它只抓取第一次出现)。但实现起来不应该太糟糕(可能还有你检查的一系列rects)。
UITextView帮助
为方便起见,我在UITextView
创建了一个扩展程序。它提供了两种方法:一种用于确定子串的矩形,另一种用于检查矩形是否可见。
rectForText
非常详细,主要是因为Range<Index>
转换为UITextRange
,事实证明这比预期更痛苦。如果有人知道更简单的方法,请分享。
extension UITextView {
func rectForText(targetText: String) -> CGRect? {
if let range = text.rangeOfString(targetText) {
let beginning = beginningOfDocument
let startOffset = text.startIndex.distanceTo(range.startIndex)
if let start = positionFromPosition(beginning, offset: startOffset) {
let endOffset = text.startIndex.distanceTo(range.endIndex) - startOffset
if let end = positionFromPosition(start, offset: endOffset) {
if let textRange = textRangeFromPosition(start, toPosition: end) {
return firstRectForRange(textRange)
}
}
}
}
return nil
}
func isRectVisible(rect: CGRect?) -> Bool {
if let rect = rect {
return CGRectIntersectsRect(rect, bounds)
}
return false
}
}
测试代码
最后,我创建了一个简单的测试项目,其中包含一个带有单个文本视图的视图控制器。请注意,它会在视图出现时检查一次可见性,然后在滚动视图滚动时连续检查。我还缓存了测试rect,以避免每次滚动时重新计算它。但如果你的文字是动态的,你就必须重新计算它。
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet weak var myTextView: UITextView!
var rectOfString: CGRect?
override func viewDidLoad() {
super.viewDidLoad()
myTextView.delegate = self
myTextView.text = "foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar My cool substring foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar "
rectOfString = myTextView.rectForText("My cool substring")
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
checkTextVisibility()
}
private func checkTextVisibility() {
if myTextView.isRectVisible(rectOfString) {
print("Visible :)")
} else {
print("Not visible :(")
}
}
}
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(scrollView: UIScrollView) {
checkTextVisibility()
}
}