簡體   English   中英

為什么我無法正確獲取導航欄和鍵盤頂部之間的高度?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM