如何向 UITextView 添加占位符文本,但在所有情况下(即使更改操作系统)都与文本定位完全匹配?

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

正如标题所说 - 添加占位符到

UITextView
很简单。

只需使用

.textDidChangeNotification
并添加
CATextLayer
甚至只是
UILabel

问题是:

绝对、准确、明确地找到相同的位置,以便占位符始终准确地位于正文所在的位置。

(因此,如果您的占位符文本是“添加您的评论”,您应该能够输入“添加您的评论”,并且它是完全相同的。)

当然,您可以简单地将文本字体/等设置为相同,但是如何绝对匹配定位,即使苹果不可避免地会在 UITextView 内部稍微移动一些东西,并且取决于它里面的内容,它自己的大小等。

如何做?

ios swift uitextview placeholder
1个回答
0
投票

我知道的唯一方法:

import UIKit

class PlaceholderTextView: UIITextView {
    
    var placeholderText: String = "" {
        didSet { placeholderLabel.text = placeholderText }
    }
    
    override func common() {
        super.common()
        clipsToBounds = true
        layer.cornerRadius = 5.0
        NotificationCenter.default.addObserver(
            self, selector: #selector(tickle),
            name: UITextView.textDidChangeNotification,
            object:nil)
    }
    
    @objc func tickle() {
        placeholderLabel.isHidden = !text.isEmpty
    }
    

然后令人惊讶的是......

    lazy private var placeholderLabel: UITextView = {
        // seems strange, but the ONLY way to truly match the position
        // at all times and in all ways, is use another text view
        let p = UITextView()
        p.isEditable = false
        p.isUserInteractionEnabled = false
        p.backgroundColor = .clear
        p.font = font
        p.textColor = (textColor ?? .black).withAlphaComponent(0.50)
        addSubview(p)
        return p
    }()
    

然后,设置幽灵文本视图的位置就很简单了:

(不要忘记复制 textContainerInset;textContainerInset 在应用程序中几乎总是会更改。)

    override func layoutSubviews() {
        super.layoutSubviews()
        placeholderLabel.textContainerInset = textContainerInset
        placeholderLabel.frame = bounds
        
        // conceivably, the font may have been changed dynamically:
        placeholderLabel.font = font
        placeholderLabel.textColor =
         (textColor ?? .black).withAlphaComponent(0.50)
        
        tickle()
    }
}

如何进行单元测试...

    @objc func tickle() {
        placeholderLabel.isHidden = !text.isEmpty
    }

更改为

    @objc func tickle() {
        placeholderLabel.isHidden = false //!text.isEmpty
    }

然后执行此测试:

因此,如果您的占位符文本是“添加您的评论”,您应该能够输入“添加您的评论”,并且它是完全相同的。

精确匹配示例:

脚注

示例类中的

common()
初始化器是什么?在项目中,我只是为各种 iOS 视图添加简单的初始化视图以节省打字。 (注意初始化时额外的“I”。)

所以:

import UIKit
class UIITextView: UITextView {
    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        common()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        common()
    }
    func common() {}
}

例如,

© www.soinside.com 2019 - 2024. All rights reserved.