[英]Resize the screen when keyboard appears
我正在構建一個聊天應用程序。 出現鍵盤時,我必須移動文本字段。 我正在使用以下代碼執行此操作:
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
kbHeight = keyboardSize.height
self.animateTextField(true)
}
}
}
func keyboardWillHide(notification: NSNotification) {
self.animateTextField(false)
}
func animateTextField(up: Bool) {
var movement = (up ? -kbHeight : kbHeight)
UIView.animateWithDuration(0.3, animations: {
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
})
}
但是當我使用此代碼時,第一條消息不會顯示。 我想我必須調整 tableview 的大小。
以下是鍵盤出現之前和之后的屏幕截圖:
我正在使用自動布局。
我該如何解決這個問題?
您可以創建表格視圖底部自動布局約束的出口。
然后只需使用此代碼:
func keyboardWillShow(sender: NSNotification) {
let info = sender.userInfo!
var keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
bottomConstraint.constant = keyboardSize - bottomLayoutGuide.length
let duration: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() }
}
func keyboardWillHide(sender: NSNotification) {
let info = sender.userInfo!
let duration: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
bottomConstraint.constant = 0
UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() }
}
如果您在創建底部約束時遇到問題:
在故事板中
|-[]-|
.現在您可以將它拖到您的視圖控制器並將其添加為插座。
另一種解決方案是設置tableView.contentInset.bottom
。 但我以前沒有這樣做過。 如果你願意,我可以試着解釋一下。
使用插圖:
func keyboardWillShow(sender: NSNotification) {
let info = sender.userInfo!
let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
tableView.contentInset.bottom = keyboardSize
}
func keyboardWillHide(sender: NSNotification) {
tableView.contentInset.bottom = 0
}
您可以嘗試使用此代碼來設置插圖。 我自己還沒有嘗試過,但應該是這樣的。
編輯:根據 nacho4d 的建議更改了持續時間
正確使用約束...
KUIViewController
下面的KUIViewController
粘貼到您的項目中,
創建一個對“內容底部”非常簡單的約束。
將該約束bottomConstraintForKeyboard
KUIViewController 將始終自動正確地調整內容視圖的大小。
絕對一切都是完全自動的。
所有 Apple 行為都以標准方式正確處理,例如通過點擊關閉等。
你已經 100% 完成了。
你不能使用.view
...
因為......你不能在 iOS 中調整.view
大小!!!!!! 哦!
只需制作一個名為“holder”的 UIView。 它位於.view
。
把你的所有東西都放在“持有人”里。
Holder 當然會有四個簡單的約束 top/bottom/left/right 到.view
。
“持有人”的底部約束確實是bottomConstraintForKeyboard
。
你完成了。
給客戶寄一張賬單然后去喝酒。
沒有什么可做的了。
class KUIViewController: UIViewController {
// KBaseVC is the KEYBOARD variant BaseVC. more on this later
@IBOutlet var bottomConstraintForKeyboard: NSLayoutConstraint!
@objc func keyboardWillShow(sender: NSNotification) {
let i = sender.userInfo!
let s: TimeInterval = (i[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
let k = (i[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
bottomConstraintForKeyboard.constant = k
// Note. that is the correct, actual value. Some prefer to use:
// bottomConstraintForKeyboard.constant = k - bottomLayoutGuide.length
UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}
@objc func keyboardWillHide(sender: NSNotification) {
let info = sender.userInfo!
let s: TimeInterval = (info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
bottomConstraintForKeyboard.constant = 0
UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}
@objc func clearKeyboard() {
view.endEditing(true)
// (subtle iOS bug/problem in obscure cases: see note below
// you may prefer to add a short delay here)
}
func keyboardNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow),
name: UIResponder.keyboardWillShowNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide),
name: UIResponder.keyboardWillHideNotification,
object: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
keyboardNotifications()
let t = UITapGestureRecognizer(target: self, action: #selector(clearKeyboard))
view.addGestureRecognizer(t)
t.cancelsTouchesInView = false
}
}
簡單地 ...
class AddCustomer: KUIViewController, SomeProtocol {
class EnterPost: KUIViewController {
class EditPurchase: KUIViewController {
在那些屏幕上,現在關於鍵盤的一切都是完全自動的。
你完成了。
呼。
*小腳注 - 背景點擊正確關閉鍵盤。 這包括落在您內容上的點擊次數。 這是正確的 Apple 行為。 任何不尋常的變化都需要大量非常反蘋果的定制編程。
*非常小的腳注 - 因此,屏幕上的任何和所有按鈕每次都可以 100% 正確工作。 然而,在嵌套 (!) 滾動視圖中嵌套 (!) 容器視圖和嵌套 (!) 頁面視圖容器 (!!!!) 的令人難以置信的模糊情況下,您可能會發現按鈕似乎不起作用。 這似乎是當前 iOS 中的一個(晦澀的!)問題。 如果您遇到這個令人難以置信的晦澀問題,幸運的是解決方案很簡單。 查看函數clearKeyboard()
,只需添加一個短暫的延遲,就完成了。
@objc func clearKeyboard() {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
self.view.endEditing(true)
}
}
(來自用戶@wildcat12 https://stackoverflow.com/a/57698468/294884 的一個很好的提示)
來自@Fattie 的消息:
細節 -(不幸的是)點擊您的內容也會關閉鍵盤。 (他們都得到了這個事件。)然而,這幾乎總是正確的行為; 試一試。 沒有合理的方法可以避免這種情況,所以忘記它並使用 Apple 流程。
這可以通過實現以下UIGestureRecognizerDelegate的方法來解決:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return !(touch.view?.isKind(of: UIControl.self) ?? true)
}
這樣,如果用戶觸摸任何UIControl
(UIButton、UITextField 等),手勢識別器將不會調用clearKeyboard()
方法。
為此,請記住在類定義或擴展中對 UIGestureRecognizerDelegate 進行子類化。 然后,在 viewDidLoad() 中,您應該將手勢識別器委托指定為 self。
准備復制和粘貼代碼:
// 1. Subclass UIGestureRecognizerDelegate
class KUIViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet var bottomConstraintForKeyboard: NSLayoutConstraint!
func keyboardWillShow(sender: NSNotification) {
let i = sender.userInfo!
let k = (i[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
bottomConstraintForKeyboard.constant = k - bottomLayoutGuide.length
let s: TimeInterval = (i[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}
func keyboardWillHide(sender: NSNotification) {
let info = sender.userInfo!
let s: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
bottomConstraintForKeyboard.constant = 0
UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}
func keyboardNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow),
name: Notification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide),
name: Notification.Name.UIKeyboardWillHide,
object: nil)
}
func clearKeyboard() {
view.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
keyboardNotifications()
let t = UITapGestureRecognizer(target: self, action: #selector(clearKeyboard))
view.addGestureRecognizer(t)
t.cancelsTouchesInView = false
// 2. Set the gesture recognizer's delegate as self
t.delegate = self
}
// 3. Implement this method from UIGestureRecognizerDelegate
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return !(touch.view?.isKind(of: UIControl.self) ?? true)
}
}
如果您不想自己解決這個問題,您可能會發現TPKeyboardAvoiding框架很有用
只需按照“安裝說明”即可,即將適當的 .h/.m 文件拖放到您的項目中,然后讓您 ScrollView/TableView 成為如下子類:
也許它會幫助某人。 您可以在不使用界面構建器的情況下實現所需的行為
首先,您需要創建約束並計算安全區域插入,以便正確支持無按鈕設備
var container: UIView!
var bottomConstraint: NSLayoutConstraint!
let safeInsets = UIApplication.shared.windows[0].safeAreaInsets
然后在代碼中的某處初始化它
container = UIView()
bottomConstraint = container.bottomAnchor.constraint(equalTo: view.bottomAnchor)
附加它以查看和激活
view.addSubview(container)
NSLayoutConstraint.activate([
...
container.leadingAnchor.constraint(equalTo: view.leadingAnchor),
container.trailingAnchor.constraint(equalTo: view.trailingAnchor),
container.topAnchor.constraint(equalTo: view.topAnchor),
bottomConstraint,
...
])
最后
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if bottomConstraint.constant == 0 {
bottomConstraint.constant = -keyboardSize.height + safeInsets.bottom
view.layoutIfNeeded()
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
bottomConstraint.constant = 0
view.layoutIfNeeded()
}
此外,如果您的視圖是可滾動的,並且您想用鍵盤將其向上移動並在鍵盤隱藏時返回到初始位置,則可以更改視圖的 contentOffset
view.contentOffset = CGPoint(x: view.contentOffset.x, y: view.contentOffset.y + keyboardSize.height - safeInsets.bottom)
向上滾動,以及
view.contentOffset = CGPoint(x: view.contentOffset.x, y: view.contentOffset.y - keyboardSize.height + safeInsets.bottom)
將其向下移動
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.