[英]Why can't I get the height between the nav bar and the top of the keyboard correctly?
我有一個奇怪的問題。 無論我在哪個 iOS 設備上運行應用程序,我都試圖計算導航欄底部和鍵盤頂部之間的確切高度。 這是我進行此計算的方法:
@objc func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height
let viewableArea = screenSize.height - keyboardRectangle.height - reportPostInstructionContainerViewHeight - characterCountContainerViewHeight - reportPostInstructionContainerViewHeight + 4
//iPhone 12 and above is "- 20"; iPhone 8 needs to be "+ 4"; iPhone 12 mini is "- 24"
print("**** navigationBarHeight: \(navigationBarHeight)")
print("**** keyboardHeight: \(keyboardHeight)")
print("**** screenSize.height: \(screenSize.height)")
print("**** total screen height - keyboard height: \(screenSize.height - keyboardRectangle.height)")
print("**** viewableArea: \(viewableArea)")
textViewHeight = viewableArea
print("**** textViewHeight: \(textViewHeight)")
UIView.animate(withDuration: 0.01, animations: { () -> Void in
self.textView.anchor(
top: self.horizontalDividerView.bottomAnchor,
leading: self.view.leadingAnchor,
bottom: nil,
trailing: self.view.trailingAnchor,
identifier: "ReportPostPFAVC.textView.directionalAnchors",
size: .init(width: 0, height: self.textViewHeight)
)
self.textView.layoutIfNeeded()
})
}
}
正在計算“viewableArea”的那一行似乎是問題所在。 例如,如果我在 iPhone 8 上運行該應用程序,我需要將 4 添加到此計算中,以便正確調整文本視圖的大小。
這是一張圖片供參考:
我試圖讓帶有“報告”按鈕的欄完美地坐在鍵盤頂部。 但是,如果我在不同的設備上進行測試,有時我需要減去 20 或 24 而不是加 4。
我真的不明白這個差距從何而來。
任何人都可以建議嗎?
**** 編輯 ****
似乎可以使用下面指示的修復程序
我將嘗試從不同的角度解決這個問題,因為我不確定您的問題究竟出在哪里,以及您提供的代碼中的邏輯到底是什么。
您需要實現的是在同一坐標系中找到兩個框架的坐標。 兩個框架是; 鍵盤框架和導航欄框架。 並且“相同坐標系”最好由您的視圖之一定義,例如視圖控制器的視圖。
UIView
上有convert
方法,旨在將幀轉換為/從不同的坐標系(例如視圖)轉換。
所以在你的情況下,你需要做的就是
let targetView = self.view!
let convertedNavigationBarFrame = targetView.convert(self.navigationController!.navigationBar.bounds, from: self.navigationController!.navigationBar)
let convertedKeyboardFrame = targetView.convert(keyboardFrame.cgRectValue, from: nil)
在這個例子中,我使用self.view
作為我想要兩個框架的坐標系。 這意味着坐標將在視圖控制器內。 要獲得兩個框架之間的高度(這是您的問題),我絕對可以使用處於同一窗口層次結構中的任何視圖,並且應該得到相同的結果。
然后在這個例子中,我將導航欄的邊界從導航欄轉換為目標視圖。 我發現這是處理UIView
框架時的最佳方法。
最后我將鍵盤框架轉換為目標視圖。 鍵盤框架有一個屏幕坐標系,導致使用from: nil
。
獲得它們之間的垂直距離是兩個垂直坐標的簡單減法
convertedKeyboardFrame.minY - convertedNavigationBarFrame.maxY
為了有一個完整的例子,我創建了一個新項目。 在故事板中:
示例代碼:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
self.navigationController?.navigationBar.backgroundColor = .green
}
private lazy var checkView: UIView = {
let checkView = UIView(frame: .zero)
checkView.backgroundColor = UIColor.black
checkView.layer.borderColor = UIColor.red.cgColor
checkView.layer.borderWidth = 5
self.view.addSubview(checkView)
return checkView
}()
@objc func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
let targetView = self.view!
let convertedNavigationBarFrame = targetView.convert(self.navigationController!.navigationBar.bounds, from: self.navigationController!.navigationBar)
let convertedKeyboardFrame = targetView.convert(keyboardFrame.cgRectValue, from: nil)
checkView.frame = CGRect(x: 30.0, y: convertedNavigationBarFrame.maxY, width: 100.0, height: convertedKeyboardFrame.minY - convertedNavigationBarFrame.maxY)
}
}
}
checkView
出現在導航欄和鍵盤之間,表明計算是正確的。 視圖應填充兩個項目之間的空間,邊框用於顯示此視圖不會延伸到鍵盤下方或導航欄上方。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.