LoginSignup
14
13

More than 5 years have passed since last update.

チャットアプリでよくある画面下部のテキストフィールドを実現する

Last updated at Posted at 2017-11-02

実現するもの

LINEのチャット画面のように、画面下部に設置されたテキストフィールドをタップすると、
出てきたキーボードの上部にスライドするようにする。

コツ

通常はUITextFieldへinputAccessoryViewを設定しますが、その場合だとViewController上のビューにもともとおいてあるUITextFieldをタップして、それとは別のUITextFieldが含まれるUIViewがキーボード上部に表示されるという感じになりそうです。
そのためここではUIResponderのinputAccessoryView: UIView?をオーバーライドすることにより同一インスタンスを返すようにしています。

 注意事項

self.bottomView = ChatRoomInputView(frame:
                       CGRect(x: 0, y: self.view.frame.height-50, width: self.view.frame.width, height: 50))
self.bottomView.chatTextField.inputAccessoryView =
                       ChatRoomInputView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 50))
self.view.addSubview(bottomView)

としても同じような画面を表示することができますが、インスタンスが違うため2つのTextFieldで入力した内容が一致しません。

コード

ChatRoomViewController.swift
class ChatRoomViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    var bottomView: ChatRoomInputView!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    //画面下部とキーボード上部に同じビューを返す
    override var inputAccessoryView: UIView? {
        return bottomView
    }

    // trueを返すことで override var inputAccessoryView: UIView? が呼ばれるっぽい
    override var canBecomeFirstResponder: Bool {
        return true
    }
}

extension ChatRoomViewController {
    func setupUI() {
        tableView.keyboardDismissMode = .interactive //TableViewを下方向にスワイプした時のみキーボードを閉じる

        // frameを指定しないとだめ
        self.bottomView = ChatRoomInputView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 50))

        //self.view.addSubview(bottomView) //やったらだめ!!

    }
}

ChatRoomInputView.swift
import UIKit

class ChatRoomInputView: UIView {

    @IBOutlet weak var chatTextField: UITextField!
    @IBOutlet weak var sendButton: UIButton!

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setFromXib()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.setFromXib()
    }

    func setFromXib() {
        let nib = UINib.init(nibName: "ChatRoomInputView", bundle: nil)
        let view = nib.instantiate(withOwner: self, options: nil).first as! UIView
        self.addSubview(view)
    }
}

参考にさせていただいたサイト

https://qiita.com/ykpaco_404wm/items/659b0070bb9dbfdf1373
https://stackoverflow.com/questions/19764293/inputaccessoryview-docked-at-bottom

14
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
13