怠慢プログラマーの備忘録

怠慢でナマケモノなプログラマーの備忘録です。

swift TextField or TextViewがキーボードで隠れる現象を回避する

UITextField or UITextViewでユーザーに入力させるUIを組み立てた時に、キーボードで入力領域が隠れてしまうことが多々あります。

大体はScrollViewでスクロール領域を確保し、ユーザーにスクロールさせるように回避しますが、今回は連動的にViewごと持ち上げて回避します。

XIBの構造自体はViewControllerのUIViewの上にScrollerView、さらにUIViewを被せるような仕組みです。

f:id:ka0in:20171215224154p:plain

ViewController

import UIKit
import UserNotifications

class AlertViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    private var defaultScrollOffset: CGFloat?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.descriptionTextView.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func viewWillAppear(_ animated: Bool) {
        // 現状のscrollViewの高さを記憶する
        self.defaultScrollOffset = self.scrollView.contentOffset.y
        self.registObserveKeyboard()

    }
    
}

extension AlertViewController: UITextViewDelegate {
    
    func registObserveKeyboard() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(self.showKeyboard(notification:)),
            name: NSNotification.Name.UIKeyboardDidShow,
            object: nil
        )
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(self.hideKeyboard(notification:)),
            name: NSNotification.Name.UIKeyboardDidHide,
            object: nil
        )
    }
    
    func unregistObserveKeyboard() {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidHide, object: nil)
        self.view.endEditing(true)
    }
    
    @objc func showKeyboard(notification: Notification) {
        // keyboardのサイズを取得
        var keyboardFrame: CGRect = CGRect.zero
        if let userInfo = notification.userInfo {
            if let keyboard = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue {
                keyboardFrame = keyboard.cgRectValue
            }
        }
        
        // 画面サイズの取得
        let myBoundSize: CGSize = UIScreen.main.bounds.size
        
        
        if self.descriptionTextView.frame.size.height <= keyboardFrame.size.height + 60 {
            self.scrollView.contentOffset.y = myBoundSize.height / 3
        }
        
    }
    
    @objc  func hideKeyboard(notification: Notification) {
        if let defaultOffset = self.defaultScrollOffset {
            self.scrollView.contentOffset.y = defaultOffset
        }
    }
}

詳解 Swift 第4版

詳解 Swift 第4版