如何将光标定位在 UITextview 中占位符文本的开头

问题描述 投票:0回答:2

我花了很多时间试图解决这个简单的问题,但没有成功。我想在 UITextView 中使用一个占位符:“翻译”,当点击 UITextView 时,占位符应该留在那里,直到输入一个字符,但我需要将光标放在占位符的开头,就在“翻译”字之前,但它保持不变在我的占位符的末尾。我找到了几个答案并尝试按照以下方式进行但不起作用。占位符正确更改为黑色,但第二个命令 -> textView.selectedRange = NSMakeRange(0, 0) 没有将光标移动到开头,为什么?

  • 我用以下内容替换了 NSMakeRange 行(我读过的其他建议,但结果相同,不起作用)-> textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument)

这里是完整的代码:

class MainViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate {
    


    @IBOutlet weak var definitionField: UITextView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // setting placeholder
        definitionField.textColor = .gray
        definitionField.text = "translation"
        
        definitionField.delegate = self    }
    
    
    func textViewDidBeginEditing(_ textView: UITextView) {
        if (textView.text == "translation") {

            textView.textColor = .black
            textView.selectedRange = NSMakeRange(0, 0)
        }
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        if (textView.text == "") {
           textView.text = "translation"
           textView.textColor = .gray
        }
        textView.resignFirstResponder()
    }
ios swift uikit uitextview
2个回答
0
投票

看起来

selectedTextRange
正在由系统自动设置,在
textViewDidBeginEditing
之后,调用
becomeFirstResponder
。您可以通过使用自定义
UITextView
子类并重写来观察这一点:

override var selectedTextRange: UITextRange? {
    didSet {
        print(selectedTextRange)
    }
}

您会看到,由于您的代码,这首先被设置为

(0, 0)
,然后再次“神奇地”调用
didSet
,将
selectedTextRange
设置为
(11, 0)

我不确定调用的是哪种方法。在那之后甚至可能没有一个可覆盖的方法被调用。

一个简单的解决方案是只使用

DispatchQueue.main.async
等待将所选文本范围设置为末尾的任何内容,然后然后更改选择。

// in textViewDidBeginEditing
DispatchQueue.main.async {
    textView.selectedRange = NSMakeRange(0, 0)
}

光标会在结尾出现一小会儿,然后再回到开头。这似乎只是视觉上的。当我尝试在光标位于末尾时输入文本时,文本被插入到“翻译”之前。

就是说,您对该占位符的实现似乎与人们期望占位符的工作方式(如

UITextField
中的那个)有很大不同,尤其是当
textViewDidEndEditing
.

如果您想要类似于

UITextField
的行为,或者如果您想查看其他方法,请查看这篇文章


0
投票

这里最简单的解决方案是添加一个包含占位符的标签。然后根据文本视图中是否有文本来设置它的

isHidden
属性

这是一个工作示例,但它使用 RxSwift 来跟踪文本、颜色和字体更改。

它的作用:

  1. 创建一个标签并将其嵌入到文本视图中的适当位置。
  2. 监控文本视图的 tintColor 并更新标签的 textColor。
  3. 监控文本视图的字体并更新标签的字体。
  4. 监听文本视图的文本,根据是否有文本更新标签的isHidden属性
extension UITextView {
    func withPlaceholder(_ placeholder: String) {
        let label = {
            let result = UILabel(frame: bounds)
            result.text = placeholder
            result.numberOfLines = 0
            result.frame = result.frame.offsetBy(dx: 4, dy: 8)
            return result
        }()

        addSubview(label)

        _ = rx.observe(UIColor.self, "tintColor")
            .take(until: rx.deallocating)
            .bind(to: label.rx.textColor)

        _ = rx.observe(UIFont.self, "font")
            .map { $0 != nil ? $0 : UIFont.systemFont(ofSize: 12) }
            .take(until: rx.deallocating)
            .bind(onNext: { [weak self] font in
                label.font = font
                label.frame.size = label.sizeThatFits(self?.bounds.size ?? CGSize.zero)
            })

        _ = rx.text.orEmpty.map { !$0.isEmpty }
            .take(until: rx.deallocating)
            .bind(to: label.rx.isHidden)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.