UITextview为整个属性文本着色,而不是给定范围

时间:2019-11-05 11:08:43

标签: ios swift uikit uitextview nsattributedstring

我需要更改链接文本的颜色并使其可点击。 我从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。 但另一方面,如果我只需要将其着色为蓝色,则该行为将再次失败。

有什么主意吗?

0 个答案:

没有答案