Edited at

iMessageの入力UIのようなキーボードの表示と連動するUIを作る with RxSwift, RxKeyboard

More than 1 year has passed since last update.


概要


  • iMessage, LINEのようなテキスト入力UIでキーボードの表示に合わせて位置が動くViewを作る


イメージ

textinput.gif


サンプルリポジトリ


環境


  • Xcode 9.4

  • Swift 4.1

  • RxSwift 4.2

  • RxCocoa 4.2

  • RxKeyboard 0.8.3


簡単概要



  • RxKeyboardライブラリを使ってキーボードの高さを取得、テキスト入力UIのBottomLayoutConstraintに反映させる


ライブラリの導入


Podfile

  pod 'RxSwift'

pod 'RxCocoa'
pod 'RxKeyboard'
pod 'RxOptional'


UIを用意する

ViewController(水色のところにテキスト入力UIを配置)
テキスト入力UIView

スクリーンショット 2018-08-17 1.08.05.png
スクリーンショット 2018-08-17 1.08.21.png


ViewController


ViewController.swift

import UIKit

import RxSwift
import RxCocoa
import RxKeyboard

class ViewController: UIViewController {

@IBOutlet weak var messageInputView: MessageInputView!
@IBOutlet weak var messageInputViewBottomConstraint: NSLayoutConstraint!

private let disposeBag = DisposeBag()

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

private func setupMessageInputView() {
RxKeyboard.instance.visibleHeight
.drive(onNext: { [weak self] keyBoardHeight in
self?.messageInputViewBottomConstraint.constant = -keyBoardHeight
self?.view.layoutIfNeeded()
})
.disposed(by: disposeBag)
}
}



ViewController.xib

z.gif

@IBOutlet weak var messageInputViewBottomConstraint: NSLayoutConstraint!


  • ViewControllerのconstraintとswiftコードを繋ぐ


簡単解説

        // RxKeyboard.instance <- シングルトンインスタンス

RxKeyboard.instance.visibleHeight
.drive(onNext: { [weak self] keyboardHeight in
// keyboardの高さが変わるたびに呼ばれる
self?.messageInputViewBottomConstraint.constant = -keyboardHeight
// Viewの更新
self?.view.setNeedsLayout()
self?.view.layoutIfNeeded()
})
.disposed(by: disposeBag)


他にも



  • visibleHeightはキーボードが非表示の時に0を流しますが、 スクロールビューのcontentOffsetを調整する場合は向いていないので、0を流さないwillShowVisibleHeight を使うと良いらしいです :muscle:

// contentOffset

RxKeyboard.instance.willShowVisibleHeight
.drive(onNext: { keyboardVisibleHeight in
scrollView.contentOffset.y += keyboardVisibleHeight
})
.disposed(by: disposeBag)


  • 他にもkeyboardのframeを取得することもできるみたい(何に使うんだろう? :thinking:


more detail :arrow_down: