2017-07-30 13 views
5

शामिल करने के लिए आईओएस 11 सुरक्षित क्षेत्र बढ़ाएं आईओएस 11 में पेश की गई नई सुरक्षित क्षेत्र लेआउट मार्गदर्शिका सामग्री को नीचे बार प्रदर्शित करने से रोकने के लिए बहुत अच्छा काम करती है, लेकिन इसमें कीबोर्ड शामिल नहीं है। इसका मतलब है कि जब एक कीबोर्ड प्रदर्शित होता है, तो सामग्री अभी भी इसके पीछे छिपी हुई है और यही वह समस्या है जिसे मैं हल करने की कोशिश कर रहा हूं।कुंजीपटल

मेरा दृष्टिकोण कुंजीपटल अधिसूचनाओं को सुनने और फिर additionalSafeAreaInsets के माध्यम से सुरक्षित क्षेत्र को समायोजित करने पर आधारित है।

override func viewDidLoad() { 
    let notificationCenter = NotificationCenter.default 
    notificationCenter.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) 
    notificationCenter.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 
    notificationCenter.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil) 
} 

//MARK: - Keyboard 
extension MyViewController { 
    @objc func keyboardWillShow(notification: NSNotification) { 
     let userInfo = notification.userInfo! 
     let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height 

     additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight, right: 0) 
     UIView.animate(withDuration: 0.3) { 
      self.view.layoutIfNeeded(); 
     } 
    } 

    @objc func keyboardWillHide(notification: NSNotification) { 
     additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 
     UIView.animate(withDuration: 0.3) { 
      self.view.layoutIfNeeded(); 
     } 
    } 

    @objc func keyboardWillChange(notification: NSNotification) { 
     let userInfo = notification.userInfo! 
     let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height 

     additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardHeight, right: 0) 

     UIView.animate(withDuration: 0.3) { 
      self.view.layoutIfNeeded(); 
     } 
    } 
} 

यह अच्छी तरह से काम करता है के रूप में MyController एक UITableView कि पूरे सुरक्षित क्षेत्र के माध्यम से फैली हुई है के साथ एक UIViewController है:

यहाँ मेरी कोड है। अब जब कीबोर्ड प्रकट होता है, तो नीचे धक्का दिया जाता है ताकि कीबोर्ड के पीछे कोई भी कक्ष न हो।

समस्या नीचे सलाखों के साथ है। मेरे पास नीचे एक टूलबार भी है जो पहले से ही सुरक्षित क्षेत्र में शामिल है। इसलिए, पूर्ण कुंजीपटल ऊंचाई को अतिरिक्त सुरक्षित क्षेत्र इन्सेट के रूप में सेट करना तालिका के नीचे धक्का देता है, जो नीचे की बार की ऊंचाई से बहुत अधिक दिखाई देता है। अच्छी तरह से काम करने के लिए इस विधि के लिए, मुझे additionalSafeAreaInsets.bottom को कीबोर्ड बार के बराबर होने के लिए नीचे बार की ऊंचाई से कम करना होगा।

प्रश्न 1: नीचे सुरक्षित सुरक्षित क्षेत्र अंतर प्राप्त करने का सबसे अच्छा तरीका क्या है? मैन्युअल रूप से टूलबार का फ्रेम प्राप्त करें और इसकी ऊंचाई का उपयोग करें? या क्या सुरक्षित क्षेत्र लेआउट गाइड से सीधे अंतर प्राप्त करना संभव है?

प्रश्न 2: संभावित रूप से कीबोर्ड बार बदलने के आकार के बिना आकार को बदलने के लिए संभव होना चाहिए, इसलिए मुझे बार के फ्रेम में बदलने के लिए कुछ विधि को भी लागू करना चाहिए। क्या यह viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) में किया गया है? या कहीं और?

धन्यवाद

उत्तर

6

क्या मेरे लिए काम किया जा रहा है view.safeAreaLayoutGuide.layoutFrame के बीच चौराहे और कीबोर्ड फ्रेम गणना करने के लिए है, और फिर additionalSafeAreaInsets.bottom के रूप में है कि की ऊंचाई की स्थापना, पूरे कुंजीपटल फ्रेम ऊंचाई के बजाय। मेरे पास मेरे व्यू कंट्रोलर में टूलबार नहीं है, लेकिन मेरे पास टैब बार है और इसे सही तरीके से माना जाता है।

पूरा कोड:

extension UIViewController { 

    func startAvoidingKeyboard() { 
     NotificationCenter.default.addObserver(self, 
               selector: #selector(_onKeyboardFrameWillChangeNotificationReceived(_:)), 
               name: NSNotification.Name.UIKeyboardWillChangeFrame, 
               object: nil) 
    } 

    func stopAvoidingKeyboard() { 
     NotificationCenter.default.removeObserver(self, 
                name: NSNotification.Name.UIKeyboardWillChangeFrame, 
                object: nil) 
    } 

    @objc private func _onKeyboardFrameWillChangeNotificationReceived(_ notification: Notification) { 
     guard let userInfo = notification.userInfo, 
      let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { 
       return 
     } 

     let keyboardFrameInView = view.convert(keyboardFrame, from: nil) 
     let safeAreaFrame = view.safeAreaLayoutGuide.layoutFrame.insetBy(dx: 0, dy: -additionalSafeAreaInsets.bottom) 
     let intersection = safeAreaFrame.intersection(keyboardFrameInView) 

     let animationDuration: TimeInterval = (notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 
     let animationCurveRawNSN = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber 
     let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue 
     let animationCurve = UIViewAnimationOptions(rawValue: animationCurveRaw) 

     UIView.animate(withDuration: animationDuration, delay: 0, options: animationCurve, animations: { 
      self.additionalSafeAreaInsets.bottom = intersection.height 
      self.view.layoutIfNeeded() 
     }, completion: nil) 
    } 
} 
+0

आईफोनएक्स से निपटने के लिए यह एक बेहतर समाधान है, क्योंकि इसकी ऊंचाई में शामिल हैं सुरक्षित क्षेत्र के बाहर –

+0

... लेकिन दुर्भाग्यवश यह सुरक्षित एरियालाउआउटगाइड का उपयोग करता है, जो आईओएस 11-केवल है और मुझे आईओएस 9 –

+0

पर समर्थन करने की आवश्यकता है क्या आपको इस और आईफोन एक्स के साथ कोई समस्या नहीं है? कीबोर्ड की वाई स्थिति, जब आईफोन एक्स पर दिखाया गया है, वास्तविक स्क्रीन की तुलना में थोड़ा अधिक लगता है। – Jonny

3

तुम वापस समर्थन IOS11 संस्करणों पूर्व आप फैबियो से समारोह का उपयोग करें और जोड़ सकते हैं करने के लिए की जरूरत है:

if #available(iOS 11.0, *) { } 

अंतिम समाधान:

extension UIViewController { 

    func startAvoidingKeyboard() { 
     NotificationCenter.default.addObserver(self, 
               selector: #selector(_onKeyboardFrameWillChangeNotificationReceived(_:)), 
               name: NSNotification.Name.UIKeyboardWillChangeFrame, 
               object: nil) 
    } 

    func stopAvoidingKeyboard() { 
     NotificationCenter.default.removeObserver(self, 
                name: NSNotification.Name.UIKeyboardWillChangeFrame, 
                object: nil) 
    } 

    @objc private func _onKeyboardFrameWillChangeNotificationReceived(_ notification: Notification) { 
     if #available(iOS 11.0, *) { 

      guard let userInfo = notification.userInfo, 
       let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { 
        return 
      } 

      let keyboardFrameInView = view.convert(keyboardFrame, from: nil) 
      let safeAreaFrame = view.safeAreaLayoutGuide.layoutFrame.insetBy(dx: 0, dy: -additionalSafeAreaInsets.bottom) 
      let intersection = safeAreaFrame.intersection(keyboardFrameInView) 

      let animationDuration: TimeInterval = (notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0 
      let animationCurveRawNSN = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber 
      let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue 
      let animationCurve = UIViewAnimationOptions(rawValue: animationCurveRaw) 

      UIView.animate(withDuration: animationDuration, delay: 0, options: animationCurve, animations: { 
       self.additionalSafeAreaInsets.bottom = intersection.height 
       self.view.layoutIfNeeded() 
      }, completion: nil) 
     } 
    } 
} 
संबंधित मुद्दे