📕

UITextViewにPlaceholderを表示する

2023/12/27に公開

はじめに

UITextViewには標準でPlaceholderが付いていないので、自分で実装するか、UITextView+Placeholderなどのライブラリを使用する必要があります。

VoicyではUITextView+Placeholderライブラリを使っていましたが、自分で実装できるものはライブラリを使わずに実装してライブラリを消したいと思ったので、消しました。

コード

import UIKit

class PlaceholderTextView: UITextView {
    
    var placeholderLabel = UILabel()
    
    @IBInspectable var placeholder: String? {
        didSet {
            placeholderLabel.text = placeholder
            placeholderLabel.sizeToFit()
        }
    }
    
    override var text: String! {
        didSet {
            textChanged()
        }
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        addSubview(placeholderLabel)
        placeholderLabel.translatesAutoresizingMaskIntoConstraints = false
        placeholderLabel.textColor = .lightGray
        placeholderLabel.font = font
        placeholderLabel.numberOfLines = 0
        placeholderLabel.text = placeholder
        
        let horizontalPadding = textContainer.lineFragmentPadding
        NSLayoutConstraint.activate([
            placeholderLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: textContainerInset.left + horizontalPadding),
            placeholderLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -(textContainerInset.right + horizontalPadding)),
            placeholderLabel.topAnchor.constraint(equalTo: topAnchor, constant: textContainerInset.top),
            placeholderLabel.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor, constant: -textContainerInset.bottom),
            placeholderLabel.widthAnchor.constraint(equalTo: widthAnchor)
        ])
        
        NotificationCenter.default.addObserver(self, selector: #selector(textChanged), name: UITextView.textDidChangeNotification, object: nil)
    }
    
    @objc func textChanged() {
        placeholderLabel.alpha = text.isEmpty ? 1.0 : 0.0
    }
}

解説

placeholderの値をstoryboardから指定できるようになっています。
placeholderが実際に表示される位置はtextContainerInsetとtextContainer.lineFragmentPaddingを使うことによって元々使っているUITextViewの設定通りの内側のpaddingを保ってくれます。

まとめ

自分で実装できそうなものはなるべくライブラリ無しで実装したいね

Discussion