カテゴリー: iOS

[Swift4]UITextViewにプレースホルダをつける

はじめに

こんにちは、nukkyです。
UITextFieldにはプレースホルダが標準で用意されていますが、UITextViewには用意されていません。
そこで、今回はUITextViewにプレースホルダっぽいものを表示できるようなクラスを作成したいと思います!

前提条件

Xcode 9.1
iOS 11 Simulator
Swift 4.0

 

実装

まずはUITextViewを継承したクラスを作成します。
プレースホルダをStoryboard上で確認するために@IBDesignableを宣言します。

import UIKit

@IBDesignable class PlaceHolderTextView: UITextView {

プレースホルダ表示用のUILabelを用意します

private lazy var placeHolderLabel: UILabel = UILabel(frame: CGRect(x: 6.0,
                                                                   y: 6.0,
                                                                   width: 0.0,
                                                                   height: 0.0))

プレースホルダ表示用のUILabelを構築します

private func configurePlaceHolder() {
    self.placeHolderLabel.lineBreakMode = .byWordWrapping
    self.placeHolderLabel.font = self.font
    self.placeHolderLabel.textColor = UIColor(red: 0.0,
                                              green: 0.0,
                                              blue: 0.0980392,
                                              alpha: 0.22)
    self.placeHolderLabel.backgroundColor = .clear
    self.addSubview(placeHolderLabel)
}

プレースホルダの表示/非表示を切り替えるメソッドを用意します

private func changeVisiblePlaceHolder() {
    if self.placeHolder.isEmpty || !self.text.isEmpty {
        self.placeHolderLabel.alpha = 0.0
    } else {
        self.placeHolderLabel.alpha = 1.0
    }
}

プレースホルダを用意するということはキーボードを表示し入力すると思うので、UITextViewは改行に対応しているためコードでキーボードのUIToolbarに閉じるボタンを追加します

private func setToolBar() {
    // 仮のサイズでツールバー生成
    let kbToolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 320, height: 40))
    kbToolBar.barStyle = UIBarStyle.default  // スタイルを設定
    
    kbToolBar.sizeToFit()  // 画面幅に合わせてサイズを変更
    
    // スペーサー
    let spacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: self, action: nil)
    
    // 閉じるボタン
    let commitButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(PlaceHolderTextView.commitButtonTapped))
    
    
    kbToolBar.items = [spacer, commitButton]
    
    
    self.inputAccessoryView = kbToolBar
}

@objc private func commitButtonTapped (){
    self.endEditing(true)
}

awakeFromNibで上記のメソッドをよんでおきます、それとこのタイミングでプレースホルダの表示/非表示を切り替えるためにNotificationCenterからUITextViewTextDidChangeを検知するようにします

override func awakeFromNib() {
    super.awakeFromNib()
    
    self.configurePlaceHolder()
    self.changeVisiblePlaceHolder()
    self.setToolBar()
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(textChanged),
                                           name: .UITextViewTextDidChange,
                                           object: nil)
}

@objc private func textChanged(notification: NSNotification?) {
    changeVisiblePlaceHolder()
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

最後にStoryboardからプレースホルダを編集できるように@IBInspectableを用意します

@IBInspectable var placeHolder: String = "" {
    didSet {
        self.placeHolderLabel.text = self.placeHolder
        self.placeHolderLabel.numberOfLines = 0
        self.placeHolderLabel.sizeToFit()
    }
}

 

 

さいごに

これでUITextViewにプレースホルダっぽいものを表示できるようになります!
個人的には結構UITextViewにプレースホルダをつけたい機会は多いと思っているので同じような思いをしている人のお役に立てればと。

nukky

シェア
執筆者:
nukky
タグ: Swift

最近の投稿

フロントエンドで動画デコレーション&レンダリング

はじめに 今回は、以下のように…

3週間 前

Goのクエリビルダー goqu を使ってみる

はじめに 最近携わっているとあ…

1か月 前

【Xcode15】プライバシーマニフェスト対応に備えて

はじめに こんにちは、suzu…

2か月 前

FSMを使った状態管理をGoで実装する

はじめに 一般的なアプリケーシ…

3か月 前