2017-12-02 171 views
1

我會盡可能快地嘗試。我有一個高度爲0的容器的主視圖,每當啓用鍵盤時,我將容器設置爲與鍵盤相同的高度,並且我有一個按鈕和一個電子郵件字段,並且已經爲此容器設置了約束,基本上向上推動元素。我已經將視圖設置爲在視圖加載時啓用並且其主視圖正常工作,但只要按下按鈕即可進入下一視圖,鍵盤會打開,但按鈕和電子郵件字段會留在鍵盤後面因爲約束不起作用,但是當我按home按鈕並關閉應用程序(而不是從後臺)並重新打開它時,約束正常工作。只有當我將導航控制器嵌入主視圖時纔會發生這種情況,否則它會完美地工作。有任何想法嗎?約束條件不適用於導航控制器

我在兩個視圖上都有完全相同的代碼。 Ps:對不起,很長的文章,我不知道如何解釋它。

@IBOutlet weak var emailTF: UITextField! 

@IBOutlet weak var bottomHeight: NSLayoutConstraint!` 

override func viewWillAppear(_ animated: Bool) 
{ 
    super.viewWillAppear(animated) 

    NotificationCenter.default.addObserver(
     self, 
     selector: #selector(keyboardWillShow), 
     name: NSNotification.Name.UIKeyboardWillShow, 
     object: nil 
    ) 

    // Show keyboard by default 
    emailTF.becomeFirstResponder() 
} 

@objc func keyboardWillShow(_ notification: Notification) 
{ 
     if let userInfo = notification.userInfo 
    { 
     if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue 
     { 
      bottomHeight.constant = keyboardSize.height 
      view.setNeedsLayout() 
     } 
    } 
} 

更新:我發現問題的一部分。 加載第二個視圖時,我無法獲得鍵盤高度,我將第二個視圖代碼從「viewWillAppear」更改爲「viewDidAppear」,使容器與鍵盤高度相同,但還有另一個問題。當我加載第一個視圖時,我得到271的鍵盤高度(這是正確的),當我移動到第二個視圖時,出於某種原因,鍵盤高度爲226,使textField移動45.同樣的事情發生在我按下返回按鈕從第二個視圖返回到第一個,鍵盤高度是226.當我按下home按鈕並重新打開應用程序時,無論我是哪個屏幕都可以獲得271的鍵盤高度,這是正確的高度。我做錯了什麼?

更新2:已解決!

因爲我的代碼只在沒有導航控制器的情況下工作,我有一種感覺,這是導航控制器所具有的快速動畫和轉換的功能,它阻止了代碼在加載前被讀取,所以我試圖寫這個一行代碼 emailTF.resignFirstResponder()我的按鈕動作,它的工作!所以基本上我不得不在下一個視圖中加載之前關閉鍵盤。我希望我能幫助一些有相同問題的用戶。

回答

0

首先確保包含正在更改的視圖的VC是textfield/textview的委託,然後從viewWillAppear調用.becomeFirstResponder()。確保您正確註冊/註銷鍵盤通知。如果可能的話,您可以使用滾動視圖(通過默認UIView)來包含ViewControllers子視圖,而不是改變約束。

func registerForKeyboardNotifications(){ 
    //Adding notifies on keyboard appearing 
    NotificationCenter.default.addObserver(forName: Notification.Name.UIKeyboardWillShow, object: nil, queue: nil, using: keyboardWasShown) 
    NotificationCenter.default.addObserver(forName: Notification.Name.UIKeyboardWillHide, object: nil, queue: nil, using: keyboardWillBeHidden) 
} 

func deregisterFromKeyboardNotifications(){ 
    //Removing notifies on keyboard appearing 
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardDidShow, object: nil) 
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillHide, object: nil) 
} 

func keyboardWasShown(notification: Notification) -> Void { 
    //Need to calculate keyboard exact size due to Apple suggestions 
    self.scrollView.isScrollEnabled = true 
    var info = notification.userInfo! 
    var keyboardSize:CGRect = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue 
    if keyboardSize.size.height <= 0 { // to fix bug on iOS 11 
     keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue 
    } 
    self.scrollView.contentInset.bottom = keyboardSize.height //add this much 
    self.scrollView.scrollIndicatorInsets.bottom = keyboardSize.height //scroll too it. 

    var aRect : CGRect = self.view.frame 
    aRect.size.height -= keyboardSize.height 
    if let activeField = self.activeTextView { 
     if (!aRect.contains(activeField.frame.origin)){ 
      self.scrollView.scrollRectToVisible(activeField.frame, animated: true) 
     } 
    } 
} 

func keyboardWillBeHidden(notification: Notification){ 
    self.scrollView.contentInset.bottom = 0 
    self.scrollView.isScrollEnabled = true 
    self.scrollView.alwaysBounceVertical = true 
} 
+0

我已經發現問題並更新了帖子。你提到scrollView,但在我的情況下,這將起作用,因爲我想只向上移動一個元素,使用scrollView會使事情變得複雜。感謝您的幫助! –

+0

@ AlexandreD'Acol我一直覺得使用滾動視圖替換視圖並添加上面的可重用代碼更容易。很高興聽到你解決它!照顧好你的項目並祝你好運! – RLoniello

+0

高興地瞭解它,我從來沒有使用過這種方法,但我一定會嘗試。謝謝 ! –

0

使用此行代碼self.view.layoutIfNeeded()而不是view.setNeedsLayout()

並確保對您得到正確的高度或沒有鍵盤的高度。

謝謝!

+0

謝謝,但它不工作,我改變了代碼行,沒有任何東西。此外,鍵盤的高度是正確的,因爲當我從視圖中刪除導航控制器時,它運行良好。另外,當我刪除導航控制器,並從segue取消選中「animate」框時,它也不起作用。看起來有些東西阻止了加載的約束,並且當有一些動畫允許約束正常工作時。 –

+0

爲什麼你沒有選中該框?我認爲限制在這種情況下不起作用。 – iDev750

+0

我只是爲了測試而做的,正如我之前所說的,代碼不適用於導航控制器。 –