【问题标题】:How to highlight a UITextView's text line by line in swift?如何在swift中逐行突出显示UITextView的文本?
【发布时间】:2018-08-25 01:47:47
【问题描述】:

我正在尝试逐行突出显示UITextView 中的文本。我想遍历每一行并突出显示该行以供用户查看,然后我想删除突出显示效果以准备下一行。我已经尝试过但未能创建解决方案,这是我现在最好的机会。

这是我迄今为止所做的一些工作,由于某种原因,它目前用“NSBackgroundColor 1101”填充UITextView,我不知道为什么会这样。

func highlight() {
        let str = "This is\n some placeholder\n text\nwith newlines."
        var newStr = NSMutableAttributedString(string: "")
        var arr:[String] = str.components(separatedBy: "\n")

        var attArr:[NSMutableAttributedString] = []

        for i in 0..<arr.count {
            attArr.append(NSMutableAttributedString(string: arr[i]))
        }

        for j in 0..<attArr.count {
            let range = NSMakeRange(0, attArr[j].length)
            attArr[j].addAttribute(.backgroundColor, value: UIColor.yellow, range: range)
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5){
                for m in 0..<attArr.count {
                    newStr = NSMutableAttributedString(string: "\(attArr[m])\n")
                    self.textView.attributedText = newStr

                }
            }
            attArr[j].removeAttribute(.backgroundColor, range: range)
            //remove from texview here
        }
    }

如您所见,该算法应该剥离 textView 文本并将其放入数组中,方法是将每一行分隔为新的行分隔符。 接下来要做的是创建一个数组,其中填充了相同的文本,但作为可变属性字符串开始添加高亮属性。 每次出现突出显示的行时,都会有一小段延迟,直到下一行开始突出显示。如果有人可以帮助或指出正确的方向以开始正确实施,那将非常有帮助,

谢谢!

【问题讨论】:

标签: swift loops uitextview


【解决方案1】:

所以你想要这个:

您需要文本视图的内容始终是完整的字符串,突出显示一行,但您的代码将其设置为仅突出显示的行。您的代码还会安排所有亮点同时发生 (.now() + 0.5),而不是在不同时间发生。

以下是我的建议:

  1. 创建一个范围数组,每行一个范围。

  2. 使用该数组修改文本视图的textStorage,根据需要删除和添加.backgroundColor 属性以突出显示和取消突出显示行。

  3. 当您突出显示行n 时,安排突出显示行n+1。这样做有两个好处:如果需要提前取消动画会更容易更高效,如果需要让动画无休止地重复会更容易。

我使用这个游乐场创建了上面的演示:

import UIKit
import PlaygroundSupport

let text = "This is\n some placeholder\n text\nwith newlines."
let textView = UITextView(frame: CGRect(x: 0, y:0, width: 200, height: 100))
textView.backgroundColor = .white
textView.text = text

let textStorage = textView.textStorage

// Use NSString here because textStorage expects the kind of ranges returned by NSString,
// not the kind of ranges returned by String.
let storageString = textStorage.string as NSString
var lineRanges = [NSRange]()
storageString.enumerateSubstrings(in: NSMakeRange(0, storageString.length), options: .byLines, using: { (_, lineRange, _, _) in
    lineRanges.append(lineRange)
})

func setBackgroundColor(_ color: UIColor?, forLine line: Int) {
    if let color = color {
        textStorage.addAttribute(.backgroundColor, value: color, range: lineRanges[line])
    } else {
        textStorage.removeAttribute(.backgroundColor, range: lineRanges[line])
    }
}

func scheduleHighlighting(ofLine line: Int) {
    DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
        if line > 0 { setBackgroundColor(nil, forLine: line - 1) }
        guard line < lineRanges.count else { return }
        setBackgroundColor(.yellow, forLine: line)
        scheduleHighlighting(ofLine: line + 1)
    }
}

scheduleHighlighting(ofLine: 0)

PlaygroundPage.current.liveView = textView

【讨论】:

  • 哇,真是太好了,谢谢你为我解决了一个巨大的头痛。我要试试这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-12
  • 2014-06-03
  • 2015-01-08
相关资源
最近更新 更多