我需要更改链接文本的颜色并使其可点击。
我从UITextView
创建了一个简单的子类。首先,一切似乎都运行良好。但是,当我需要多次更改文本时,它将整个文本显示为蓝色,而不仅仅是链接范围。
我在此处添加游乐场代码。如果在“ TAP TAP”上点击3次,您将明白我的意思。
import UIKit
import PlaygroundSupport
final class TextViewWithLinks: UITextView {
typealias LinkParameters = [(displayText: String, urlPath: String)]
override public var text: String! {
get { attributedText.string }
set { setupText(newValue) }
}
var linkParameters: LinkParameters = [] {
didSet { setupText(text) }
}
init() {
super.init(frame: .zero, textContainer: nil)
setup()
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
backgroundColor = nil
textColor = .gray
textAlignment = .center
isSelectable = true
isEditable = false
isScrollEnabled = false
delegate = self
}
private func setupText(_ text: String) {
let newAttributedText = NSMutableAttributedString(string: text)
let textColor = self.textColor ?? .gray
let font = self.font ?? .systemFont(ofSize: 14)
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = textAlignment
newAttributedText.addAttributes(
[.font: font, .foregroundColor: textColor, .paragraphStyle: paragraph],
range: NSRange(location: 0, length: text.count)
)
for linkParameter in linkParameters {
let url = URL(string: linkParameter.urlPath)
let displayText = linkParameter.displayText.lowercased()
newAttributedText.addAttributes(
[.link: url ?? linkParameter.urlPath, .foregroundColor: UIColor.blue],
range: (text.lowercased() as NSString).range(of: displayText)
)
}
self.attributedText = newAttributedText
}
}
extension TextViewWithLinks: UITextViewDelegate {
func textView(
_ textView: UITextView,
shouldInteractWith URL: URL,
in characterRange: NSRange,
interaction: UITextItemInteraction) -> Bool {
return true
}
}
class MyViewController: UIViewController {
private let button = UIButton()
private let textView = TextViewWithLinks()
override func loadView() {
super.loadView()
let view = UIView()
view.backgroundColor = .white
textView.text = "My text with a link"
textView.linkParameters = [
(displayText: "link", urlPath: "https://www.google.com/")
]
button.setTitle("TAP TAP", for: .normal)
button.setTitleColor(.black, for: .normal)
button.addTarget(self, action: #selector(tappedButton), for: .touchUpInside)
self.view = view
layoutTextView()
layoutButton()
}
@objc private func tappedButton() {
textView.text = "\nNew line" + textView.text
}
private func layoutTextView() {
view.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50),
textView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
textView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)
])
}
private func layoutButton() {
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
button.topAnchor.constraint(equalTo: view.topAnchor, constant: 5),
button.heightAnchor.constraint(equalToConstant: 30),
button.widthAnchor.constraint(equalToConstant: 100),
button.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
唯一的解决方案是,我发现删除.foregroundColor: UIColor.blue
并仅为链接属性添加.link: url ?? linkParameter.urlPath
。
但另一方面,如果我只需要将其着色为蓝色,则该行为将再次失败。
有什么主意吗?