承上篇 - iOS - 客製化Dialog
若Dialog中有 TextField的時候, 可能會被軟體鍵盤所蓋住
因此必須使用動態調整Dialog的方式來解決.
Step 1: 監聽與取消監聽軟體鍵盤變化
在viewWillAppear監聽軟體鍵盤變化
在viewWillDisappear取消監聽
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| override func viewWillAppear(animated: Bool) { NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(Dialog.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(Dialog.keyboardWillHidden(_:)), name: UIKeyboardWillHideNotification, object: nil) }
override func viewWillDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillShow(notification: NSNotification) { }
func keyboardWillHidden(notification: NSNotification) { }
|
Step 2: Reference TextField and 監聽TextField選取變化
如果有多個TextField時, 每個TextField的位置都不一樣, 所以我們必須得知目前被選到的TextField是哪一個.
設立變數
1
| var selectedEditText : UITextField?
|
註冊TextField delegate
1 2 3 4 5
| @IBOutlet weak var mEditText: UITextField! override func viewDidLoad() { super.viewDidLoad() mEditText.delegate = self; }
|
監聽TextField選取變化
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| extension Dialog : UITextFieldDelegate { func textFieldDidBeginEditing(textField: UITextField) { selectedEditText = textField } func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() return true } func textFieldDidEndEditing(textField: UITextField) { selectedEditText = nil } }
|
Step 3: 將畫面向上調整
由於我們需要計算Dialog View在整個Frame的y軸位置, 所以必須先reference Dialog View後, 再使用mDialogView.frame.origin.y 得知y軸位置.
取得鍵盤高度
1 2 3 4 5 6
| func keyboardWillShow(notification: NSNotification) { let userInfo: NSDictionary? = notification.userInfo let aValue: NSValue? = userInfo?.objectForKey(UIKeyboardFrameEndUserInfoKey) as? NSValue let keyboardRect = aValue?.CGRectValue() let keyboardHeight = keyboardRect?.size.height }
|
計算輸入框和鍵盤高度的差值
由上圖得知 self.view.frame.size.height - keyboardHeight = 畫面剩餘空間
若mDialogVIew.frame.origin.y + frame.origin.y 的數值大於畫面剩餘空間的話,
表示輸入框會被鍵盤所覆蓋.
所以我們利用此公式來算出差值.
1
| let offset = frame.origin.y + mDialogView.frame.origin.y + 36 - (self.view.frame.size.height - keyboardHeight!)
|
36 這個數值可根據文字的大小來動態調整, 或者使用輸入框的高度
使用動畫來調整畫面
1 2 3 4 5 6 7
| UIView.animateWithDuration(0.3, animations: { () -> Void in if (offset > 0) { self.view.frame.origin.y -= offset; } else { self.view.frame.origin.y = 0; } })
|
Step 4: 輸入完畢後, 恢復畫面位置
1 2 3 4 5
| func keyboardWillHidden(notification: NSNotification) { UIView.animateWithDuration(0.3, animations: { () -> Void in self.view.frame.origin.y = 0; }) }
|
執行結果
Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| import UIKit
class Dialog: UIViewController { @IBOutlet weak var mEditText: UITextField! @IBOutlet weak var mDialogView: UIView! var selectedEditText : UITextField?
override func viewDidLoad() { super.viewDidLoad() mEditText.delegate = self; }
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
override func viewWillAppear(animated: Bool) { NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(Dialog.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(Dialog.keyboardWillHidden(_:)), name: UIKeyboardWillHideNotification, object: nil) }
override func viewWillDisappear(animated: Bool) { NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) }
func keyboardWillShow(notification: NSNotification) { let userInfo: NSDictionary? = notification.userInfo let aValue: NSValue? = userInfo?.objectForKey(UIKeyboardFrameEndUserInfoKey) as? NSValue let keyboardRect = aValue?.CGRectValue() let keyboardHeight = keyboardRect?.size.height
let frame = selectedEditText!.frame let offset = frame.origin.y + mDialogView.frame.origin.y + 36 - (self.view.frame.size.height - keyboardHeight!)
UIView.animateWithDuration(0.3, animations: { () -> Void in if (offset > 0) { self.view.frame.origin.y -= offset; } else { self.view.frame.origin.y = 0; } }) }
func keyboardWillHidden(notification: NSNotification) { UIView.animateWithDuration(0.3, animations: { () -> Void in self.view.frame.origin.y = 0; }) } }
extension Dialog : UITextFieldDelegate { func textFieldDidBeginEditing(textField: UITextField) { selectedEditText = textField } func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() return true }
func textFieldDidEndEditing(textField: UITextField) { selectedEditText = nil } }
|