ย้ายฟิลด์ข้อความเมื่อคีย์บอร์ดปรากฏอย่างรวดเร็ว


217

ฉันใช้ Swift สำหรับการวางโปรแกรมกับ iOS และฉันใช้รหัสนี้เพื่อย้ายUITextFieldแต่มันใช้งานไม่ได้ ฉันเรียกใช้ฟังก์ชันkeyboardWillShowได้อย่างถูกต้อง แต่ฟิลด์ข้อความไม่ขยับ ฉันกำลังใช้การชำระอัตโนมัติ

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self);
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        //let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)

        var frame = self.ChatField.frame
        frame.origin.y = frame.origin.y - keyboardSize.height + 167
        self.chatField.frame = frame
        println("asdasd")
    }
}

2
คู่มือการใช้งานพร้อมไฟล์โครงการ: codebeaulieu.com/43/…
Dan Beaulieu

บางที deinit และ viewDidLoad อาจไม่สมดุลกัน
Ricardo

ขึ้นอยู่กับเอกสารของ Apple และประสบการณ์ส่วนตัว นี่คือ git repo ของฉันโดยใช้ UIScrollView เพื่อย้าย TF: github.com/29satnam/MoveTextFieldWhenKeyboardAppearsSwift
Codetard

คำตอบ:


315

มีการปรับปรุงสองสามอย่างที่ต้องทำกับคำตอบที่มีอยู่

ประการแรกUIKeyboardWillChangeFrameNotificationน่าจะเป็นการแจ้งเตือนที่ดีที่สุดเพราะมันจัดการการเปลี่ยนแปลงที่ไม่เพียงแค่แสดง / ซ่อน แต่การเปลี่ยนแปลงเนื่องจากการเปลี่ยนแปลงของแป้นพิมพ์ (ภาษาการใช้แป้นพิมพ์ของบุคคลที่สามเป็นต้น) และการหมุนด้วย (แต่หมายเหตุความคิดเห็นด้านล่าง ยังได้รับการจัดการเพื่อรองรับการเชื่อมต่อแป้นพิมพ์ฮาร์ดแวร์)

ประการที่สองพารามิเตอร์ภาพเคลื่อนไหวสามารถดึงออกมาจากการแจ้งเตือนเพื่อให้แน่ใจว่าภาพเคลื่อนไหวมีความเหมาะสม

อาจมีตัวเลือกในการล้างข้อมูลรหัสนี้อีกเล็กน้อยโดยเฉพาะอย่างยิ่งถ้าคุณรู้สึกสบายใจที่จะบังคับให้แกะรหัสพจนานุกรมออกมา

สวิฟท์ 3

class MyViewController: UIViewController {

// This constraint ties an element at zero points from the bottom layout guide
@IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint?

override func viewDidLoad() {
    super.viewDidLoad()
    // Note that SO highlighting makes the new selector syntax (#selector()) look
    // like a comment but it isn't one
    NotificationCenter.default.addObserver(self,
        selector: #selector(self.keyboardNotification(notification:)),
        name: NSNotification.Name.UIKeyboardWillChangeFrame,
        object: nil)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

@objc func keyboardNotification(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
        let endFrameY = endFrame.origin.y ?? 0
        let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue
        let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
        if endFrameY >= UIScreen.main.bounds.size.height {
            self.keyboardHeightLayoutConstraint?.constant = 0.0
        } else {
            self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
        }
        UIView.animate(withDuration: duration,
                                   delay: TimeInterval(0),
                                   options: animationCurve,
                                   animations: { self.view.layoutIfNeeded() },
                                   completion: nil)
    }
}

(แก้ไขเพื่อบัญชีสำหรับแป้นพิมพ์เคลื่อนไหวหน้าจอแทนการหดตัวตามความคิดเห็นที่น่ากลัวของ @ Gabox ด้านล่าง)

สวิฟท์ 5

class MyViewController: UIViewController {

// This constraint ties an element at zero points from the bottom layout guide
@IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint?

override func viewDidLoad() {
    super.viewDidLoad()
    // Note that SO highlighting makes the new selector syntax (#selector()) look
    // like a comment but it isn't one
    NotificationCenter.default.addObserver(self,
        selector: #selector(self.keyboardNotification(notification:)),
        name: UIResponder.keyboardWillChangeFrameNotification,
        object: nil)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

@objc func keyboardNotification(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
        let endFrameY = endFrame?.origin.y ?? 0
        let duration:TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
        let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
        if endFrameY >= UIScreen.main.bounds.size.height {
            self.keyboardHeightLayoutConstraint?.constant = 0.0
        } else {
            self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
        }
        UIView.animate(withDuration: duration,
                                   delay: TimeInterval(0),
                                   options: animationCurve,
                                   animations: { self.view.layoutIfNeeded() },
                                   completion: nil)
    }
}

1
@JosephLord ดี แต่ฉันพบว่าสิ่งนี้ไม่ทำงานเมื่อแป้นพิมพ์ซ่อนอยู่เพราะendFrame?.size.heightไม่ใช่ศูนย์ UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 1024}, {768, 264}}";ผมได้เฟรมสุดท้ายเป็น Ran บน iOS 8.3 iPad Simulator, รูปบุคคล Xcode6.3 beta4
Hlung

8
หากแป้นพิมพ์ไม่ซ่อนลองใช้รหัสนี้ถ้า endFrame? .origin.y> = UIScreen.mainScreen (). bounds.size.height {self.keyboardHeightLayoutConstraint? .constant = 0.0} อื่น {self.keyboardHeightLayoutConstraint? = endFrame.size.height}
Gabriel Goncalves

3
keyBoardHeightLayoutConstraint เป็นข้อ จำกัด ที่กำหนดไว้ใน InterfaceBuilder ซึ่ง จำกัด ด้านล่างของมุมมองที่คุณต้องการย้าย / ย่อขนาดไปที่แนวทางโครงร่างด้านล่างหรือด้านล่างของมุมมองหลักสำหรับมุมมองหลัก ค่าคงที่ถูกตั้งค่าเริ่มต้นเป็นศูนย์และจะถูกปรับเพื่อให้มีที่ว่างสำหรับแป้นพิมพ์เมื่อแป้นพิมพ์ปรากฏขึ้นหรือเปลี่ยนขนาด
โจเซฟลอร์ด

2
โปรดทราบว่า.UIKeyboardWillChangeFrameจะไม่ทำงานเมื่อเชื่อมต่อแป้นพิมพ์ฮาร์ดแวร์แม้ว่าแป้นพิมพ์ iOS จะหายไป คุณต้องสังเกต.UIKeyboardWillHideเช่นกันเพื่อจับเคสขอบนั้น
jamesk

1
@Sulthan ทำงานได้ดี .. ปัญหาของฉันคือการที่ได้รับสูงกว่า keybaord เล็กน้อย มีวิธีใดที่เราสามารถแก้ไขได้
Pavlos

128

หากคุณใช้การจัดวางอัตโนมัติฉันถือว่าคุณได้กำหนดขอบเขตด้านล่างเป็นข้อ จำกัด ของการกำกับดูแล หากเป็นเช่นนั้นคุณต้องอัปเดตค่าของข้อ จำกัด นี่คือวิธีที่คุณทำกับอนิเมชั่นเล็กน้อย

func keyboardWasShown(notification: NSNotification) {
    let info = notification.userInfo!
    let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()

    UIView.animateWithDuration(0.1, animations: { () -> Void in
        self.bottomConstraint.constant = keyboardFrame.size.height + 20
    })
}

hardcoded 20 ถูกเพิ่มเข้ามาเพื่อให้ปรากฏที่ textfield ด้านบนคีย์บอร์ดเพียงเล็กน้อย มิฉะนั้นขอบด้านบนของแป้นพิมพ์และขอบด้านล่างของฟิลด์ข้อความจะถูกสัมผัส

เมื่อคีย์บอร์ดถูกยกเลิกให้รีเซ็ตค่าของข้อ จำกัด เป็นค่าดั้งเดิม


1
คุณช่วยอธิบายฉันหน่อยได้มั้ยว่าฉันจะนิยามมันยังไง? ขอบคุณ! ฉันควบคุมทุกเรื่องบนกระดานเรื่องราวเสมอ
Pedro Manfredi

4
bottomConstraint เป็นชื่อที่ฉันมอบให้กับข้อ จำกัด ฉันเลือกข้อ จำกัด แล้วลากและสร้าง IBOutlet ลงไปและตั้งชื่อนั้น คุณสามารถสร้าง IBOutlets ให้เป็นข้อ จำกัด เช่นเดียวกับที่คุณทำกับองค์ประกอบ UI อื่น ๆ เช่นปุ่มและฟิลด์ข้อความ
Isuru

2
คำตอบนี้ใช้ได้ดีมากยกเว้นภาพเคลื่อนไหวเกิดขึ้นทันทีสำหรับฉัน ตรวจสอบฉันจะเปลี่ยนแปลงข้อ จำกัด การเคลื่อนไหวได้อย่างไร สำหรับวิธีการเคลื่อนไหวอย่างถูกต้อง
Adam Johns

2
@ vinbhai4u คุณต้องลงทะเบียนเพื่อรับการUIKeyboardWillShowNotificationแจ้งเตือน ดูรหัสในคำถามของ OP
Isuru

8
@AdamJohns หากต้องการเคลื่อนไหวการเปลี่ยนแปลงข้อ จำกัด ให้อัปเดตค่าคงที่ภายนอกanimateWithDurationและโทรself.view.layoutIfNeeded()ภายในบล็อกการเคลื่อนไหว
สูงสุด

110

ทางออกที่ง่ายคือเลื่อนดูขึ้นด้วยความสูงของคีย์บอร์ด

override func viewDidLoad() {
   super.viewDidLoad()        
   NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
   NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}

@objc func keyboardWillShow(sender: NSNotification) {
     self.view.frame.origin.y = -150 // Move view 150 points upward 
}

@objc func keyboardWillHide(sender: NSNotification) {
     self.view.frame.origin.y = 0 // Move view to original position  
}

สวิฟท์ 5:

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(sender:)), name: UIResponder.keyboardWillShowNotification, object: nil);

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(sender:)), name: UIResponder.keyboardWillHideNotification, object: nil);

4
ฉันชอบวิธีแก้ปัญหาง่ายๆนี้ แต่ฉันเพิ่มคีย์บอร์ดการแสดงบูลีนเนื่องจากฉันย้ายมากกว่าหนึ่งฟิลด์ข้อความ ฉันย้ายคีย์บอร์ดเพียงครั้งเดียวขณะที่แสดง ขอบคุณ
เคน

2
แทนที่จะย้ายมุมมองย้าย textView
ericgu

1
นี่จะเป็นการลบค่า y ของมุมมองหากผู้ใช้สลับภาษาที่ป้อน
Jeffrey Neo

แทนที่จะเปลี่ยนมุมมองตัวเองฉันทำค่าตัวเอง จำกัด ตัวเองมันใช้งานได้ แต่สิ่งที่เป็นมุมมอง (ซึ่งมีการใช้ข้อ จำกัด ) ช่วยให้เลื่อนขึ้น ไม่มีใครประสบปัญหานี้หรือไม่?
Sashi

5
แทนการใช้self.view.frame.origin.y -= 150การใช้งานself.view.frame.origin.y = -150และแทนที่จะใช้self.view.frame.origin.y += 150 self.view.frame.origin.y = 0สิ่งนี้จะป้องกันไม่ให้มุมมองเคลื่อนที่ 150 ในแต่ละครั้งที่มีการสัมผัสฟิลด์ใหม่
gunwin

43

สำหรับการย้ายมุมมองของคุณในขณะที่แก้ไข textfield ลองนี่ฉันได้ใช้สิ่งนี้

ตัวเลือกที่ 1: - ** ** อัพเดทใน Swift 5.0 และ iPhone X, XR, XS และ XS Max Move โดยใช้ NotificationCenter

  • ลงทะเบียนประกาศนี้ใน func viewWillAppear(_ animated: Bool)

  • ลงทะเบียนการแจ้งเตือนนี้ใน func viewWillDisappear(_ animated: Bool)

หมายเหตุ: - หากคุณจะไม่ลงทะเบียนเกินกว่าที่จะโทรจากชั้นเด็กและจะเหตุผลของการกระแทกหรืออื่น ๆ

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillShow(notification:)), name:  UIResponder.keyboardWillShowNotification, object: nil )
}
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
}

@objc func keyboardWillShow( notification: Notification) {
    if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
        var newHeight: CGFloat
        let duration:TimeInterval = (notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
        let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
        if #available(iOS 11.0, *) {
            newHeight = keyboardFrame.cgRectValue.height - self.view.safeAreaInsets.bottom
        } else {
            newHeight = keyboardFrame.cgRectValue.height
        }
        let keyboardHeight = newHeight  + 10 // **10 is bottom margin of View**  and **this newHeight will be keyboard height**
        UIView.animate(withDuration: duration,
                       delay: TimeInterval(0),
                       options: animationCurve,
                       animations: {
                        self.view.textViewBottomConstraint.constant = keyboardHeight **//Here you can manage your view constraints for animated show**
                        self.view.layoutIfNeeded() },
                       completion: nil)
    }
}

ตัวเลือกที่ 2: - ทำงานได้ดี

func textFieldDidBeginEditing(textField: UITextField) {
        self.animateViewMoving(up: true, moveValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
        self.animateViewMoving(up: false, moveValue: 100)
}

func animateViewMoving (up:Bool, moveValue :CGFloat){
    var movementDuration:NSTimeInterval = 0.3
    var movement:CGFloat = ( up ? -moveValue : moveValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration )
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}

ฉันได้รับคำตอบนี้จากแหล่งที่มาUITextField เลื่อนขึ้นเมื่อแป้นพิมพ์ปรากฏใน Swift

ในสวิฟต์ 4 ---

func textFieldDidBeginEditing(_ textField: UITextField) {
        animateViewMoving(up: true, moveValue: 100)
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        animateViewMoving(up: false, moveValue: 100)
    }
    func animateViewMoving (up:Bool, moveValue :CGFloat){
        let movementDuration:TimeInterval = 0.3
        let movement:CGFloat = ( up ? -moveValue : moveValue)
        UIView.beginAnimations( "animateView", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(movementDuration ) 
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }

1
@ Jogendra.Com ขอบคุณสำหรับ work.But ฮาร์ดดิสก์ของคุณมันทำงานได้ดีที่สุดบน iPhone และ 5,4s 6.But ว่าฉันสามารถปิดการใช้งานบน iPhone และ iPad 6plus (คนสูงกว่า)
Thiha Aung

หากคุณกำลังใช้ตัวเลือกที่ 1 โปรดตรวจสอบให้แน่ใจว่าได้เพิ่มข้อ จำกัด IBOutlet คุณจะสร้างข้อ จำกัด ที่คุณต้องการปรับขนาดโดยใช้เลย์เอาต์อัตโนมัติแล้วลากและวางลงในวิวเวอร์คอนโทรลเพื่อสร้าง IBOutlet ที่ฉันอ้างถึงเป็น self.iboutletConstraint.constant ในฟังก์ชั่นภาพเคลื่อนไหว นอกจากนี้สิ่งนี้ไม่ได้ปรับเต้าเสียบใหม่เมื่อซ่อนแป้นพิมพ์ฉันจัดการมันด้วยการรีเซ็ตข้อ จำกัด ให้เป็นค่าดั้งเดิม
Hammad Tariq

21

ฉันรักรหัส Swift ที่สะอาดตา ดังนั้นนี่คือรหัสที่รัดกุมที่สุดที่ฉันสามารถหาได้เพื่อเลื่อนมุมมองข้อความขึ้น / ลงด้วยคีย์บอร์ด กำลังทำงานในแอปพลิเคชั่นการผลิต iOS8 / 9 Swift 2

อัปเดต (มีนาคม 2559): ฉันเพิ่งทำให้โค้ดก่อนหน้าของฉันแน่นมากที่สุดเท่าที่จะทำได้ นอกจากนี้ยังมีคำตอบที่ได้รับความนิยมมากมายที่นี่ซึ่ง hardcode ความสูงของแป้นพิมพ์และพารามิเตอร์ภาพเคลื่อนไหว ไม่จำเป็นต้องพูดถึงตัวเลขในคำตอบเหล่านี้ไม่ได้สอดคล้องกับค่าจริงที่ฉันเห็นใน 6s + iOS9 ของฉันเสมอ (ความสูงของคีย์บอร์ด 226, ระยะเวลา 0.25 และเส้นโค้งภาพเคลื่อนไหว 7) ไม่ว่าในกรณีใดมันแทบจะไม่มีโค้ดพิเศษใด ๆ ที่จะนำค่าเหล่านั้นมาจากระบบ ดูด้านล่าง

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "animateWithKeyboard:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "animateWithKeyboard:", name: UIKeyboardWillHideNotification, object: nil)
}

func animateWithKeyboard(notification: NSNotification) {

    // Based on both Apple's docs and personal experience, 
    // I assume userInfo and its documented keys are available.
    // If you'd like, you can remove the forced unwrapping and add your own default values.

    let userInfo = notification.userInfo!
    let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
    let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! Double
    let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as! UInt
    let moveUp = (notification.name == UIKeyboardWillShowNotification)

    // baseContraint is your Auto Layout constraint that pins the
    // text view to the bottom of the superview.

    baseConstraint.constant = moveUp ? -keyboardHeight : 0

    let options = UIViewAnimationOptions(rawValue: curve << 16)
    UIView.animateWithDuration(duration, delay: 0, options: options,
        animations: {
            self.view.layoutIfNeeded()
        },
        completion: nil
    )

}

หมายเหตุ: รหัสนี้ครอบคลุมความคิดเห็น / กรณีทั่วไปมากที่สุด อย่างไรก็ตามอาจจำเป็นต้องใช้รหัสเพิ่มเติมเพื่อจัดการกับทิศทางที่แตกต่างกันและ / หรือแป้นพิมพ์แบบกำหนดเองนี่คือบทความเชิงลึกเกี่ยวกับการทำงานกับแป้นพิมพ์ iOS หากคุณต้องการจัดการกับทุกสถานการณ์สิ่งนี้อาจช่วยได้


ดูเหมือนว่าจะเป็น Swift 1.1 และฉันคิดว่าจะไม่คอมไพล์ใน Swift 1.2 เพราะมันใช้asสำหรับการใช้พละกำลัง as!อาจทำงานได้ แต่อย่างที่คุณเห็นในที่อื่นในหน้านี้ฉันหลีกเลี่ยงการใช้กำลังและปลดตัวเองออกมา
โจเซฟลอร์ด

รวบรวมตอนนี้ใน Swift 1.2 และฉันได้เพิ่มความคิดเห็นในรหัสอีกครั้ง: การบังคับแกะ ไชโย
scootermg

อุ่ย ฉันหมายถึง Swift 2
scootermg

ทั้งนี้ขึ้นอยู่กับวิธีการที่คุณเชื่อมโยงของคุณbaseConstraintมันอาจจะแทนbaseConstraint.constant = moveUp ? keyboardHeight : 0 baseConstraint.constant = moveUp ? -keyboardHeight : 0
limfinity

15

แก้ไข : ฉันแนะนำวิธีที่ง่ายและสะอาดขึ้น เพียงแค่เปลี่ยนระดับของข้อ จำกัด ระยะห่างด้านล่างเพื่อKeyboardLayoutConstraint มันจะขยายไปยังความสูงของคีย์บอร์ดโดยอัตโนมัติ


นี่เป็นคำตอบของ @JosephLord รุ่นปรับปรุง

ผ่านการทดสอบบน iOS 8.3 iPad Simulator, Portrait Xcode6.3 Beta4 ผมพบคำตอบของเขาไม่ทำงานเมื่อแป้นพิมพ์ที่ซ่อนอยู่เพราะมีUIKeyboardFrameEndUserInfoKey "NSRect: {{0, 1024}, {768, 264}}";ความสูงไม่เคย0ความสูงไม่เคย

สิ่งนี้กลับไปใช้แบบดั้งเดิมUIKeyboardWillShowNotificationและUIKeyboardWillHideNotificationบอกได้ดีขึ้นเมื่อคีย์บอร์ดซ่อนอยู่แทนที่จะใช้ความสูงของเฟรมท้าย UIKeyboardWillShowNotificationจะถูกส่งไปเช่นกันเมื่อมีการเปลี่ยนแปลงเฟรมคีย์บอร์ดดังนั้นควรครอบคลุมทุกกรณีการใช้งาน

    // You have to set this up in storyboard first!. 
    // It's a vertical spacing constraint between view and bottom of superview.
    @IBOutlet weak var bottomSpacingConstraint: NSLayoutConstraint! 

    override func viewDidLoad() {
        super.viewDidLoad()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardNotification:"), name:UIKeyboardWillShowNotification, object: nil);
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardNotification:"), name:UIKeyboardWillHideNotification, object: nil);
    }

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    func keyboardNotification(notification: NSNotification) {

        let isShowing = notification.name == UIKeyboardWillShowNotification

        if let userInfo = notification.userInfo {
            let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
            let endFrameHeight = endFrame?.size.height ?? 0.0
            let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
            let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
            let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue
            let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
            self.bottomSpacingConstraint?.constant = isShowing ? endFrameHeight : 0.0
            UIView.animateWithDuration(duration,
                delay: NSTimeInterval(0),
                options: animationCurve,
                animations: { self.view.layoutIfNeeded() },
                completion: nil)
        }
    }

คุณช่วยอธิบายการแก้ไขของคุณได้มั้ย ฉันไม่สามารถทำงานได้ ฉันมี UIScrollView พร้อมปุ่มที่ด้านล่าง ฉันกำหนดคลาสที่ข้อ จำกัด ด้านล่างของระยะขอบด้านล่าง
schw4ndi

@ schw4ndi ข้อ จำกัด ด้านล่างของคุณเชื่อมโยงกับมุมมองแบบใด มันควรจะเชื่อมต่อด้านล่างของ scrollview ไปที่ด้านล่างของ superview ของ scrollview นั้น
Hlung

โอ้ขอบคุณฉันมีข้อ จำกัด ระหว่างปุ่มและ scrollView
schw4ndi

9

ฉันทำงานกับswift 4และฉันแก้ไขปัญหานี้ได้โดยไม่ต้องใช้ข้อ จำกัด ด้านล่างพิเศษใด ๆ ดูรหัสของฉันอยู่ที่นี่จริงๆทำงานบนกรณีของฉัน

1) เพิ่มตัวสังเกตการแจ้งเตือนที่โหลดแล้ว

override func viewDidLoad() {
        super.viewDidLoad()
        setupManager()
        // Do any additional setup after loading the view.
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

2) ลบผู้สังเกตการณ์การแจ้งเตือนเช่น

deinit {
        NotificationCenter.default.removeObserver(self)
    }

3) เพิ่มวิธีการแสดง / ซ่อนแป้นพิมพ์เช่น

 @objc func keyboardWillShow(notification: NSNotification) {
            if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
                UIView.animate(withDuration: 0.1, animations: { () -> Void in
                    self.view.frame.origin.y -= keyboardSize.height
                    self.view.layoutIfNeeded()
                })
            }
        }

@objc func keyboardWillHide(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            UIView.animate(withDuration: 0.1, animations: { () -> Void in
                self.view.frame.origin.y += keyboardSize.height
                self.view.layoutIfNeeded()
            })
        }
    }

4) เพิ่มผู้รับมอบสิทธิ์ textfeild และเพิ่มวิธีการ touchesBegan .use เต็มสำหรับซ่อนแป้นพิมพ์เมื่อสัมผัสนอก textfeild บนหน้าจอ

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        view.endEditing(true)

    }

จำเป็นต้องเป็นUIKeyboardFrameEndUserInfoKey
Micro

1
NSNotification.Name.UIKeyboardWillShow จะเปลี่ยนชื่อUIResponder.keyboardWillShowNotificationยัง UIKeyboardFrameBeginUserInfoKey ไปUIResponder.keyboardFrameBeginUserInfoKey
SMJ

7

นี่เป็นคำตอบของ @JosephLord และ @ Hlung รุ่นปรับปรุง มันสามารถนำไปใช้ไม่ว่าคุณจะมีแถบหรือไม่ และมันจะคืนค่ามุมมองที่ถูกย้ายโดยคีย์บอร์ดอย่างสมบูรณ์แบบไปยังตำแหน่งเดิม

// You have to set this up in storyboard first!. 
// It's a vertical spacing constraint between view and bottom of superview.
@IBOutlet weak var bottomSpacingConstraint: NSLayoutConstraint! 

override func viewDidLoad() {
        super.viewDidLoad()            

        //    Receive(Get) Notification
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardNotification:", name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardNotification:", name: UIKeyboardWillHideNotification, object: nil)


        self.originalConstraint = self.keyboardHeightLayoutConstraint?.constant //for original coordinate.
}

func keyboardNotification(notification: NSNotification) {
        let isShowing = notification.name == UIKeyboardWillShowNotification

        var tabbarHeight: CGFloat = 0
        if self.tabBarController? != nil {
            tabbarHeight = self.tabBarController!.tabBar.frame.height
        }
        if let userInfo = notification.userInfo {
            let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
            let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
            let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
            let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue
            let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
            self.keyboardHeightLayoutConstraint?.constant = isShowing ? (endFrame!.size.height - tabbarHeight) : self.originalConstraint!
            UIView.animateWithDuration(duration,
                delay: NSTimeInterval(0),
                options: animationCurve,
                animations: { self.view.layoutIfNeeded() },
                completion: nil)
        }
}

6

วิธีที่ง่ายที่สุดที่ไม่ต้องใช้รหัสใด ๆ :

  1. ดาวน์โหลดKeyboardLayoutConstraint.swiftและเพิ่ม (ลากและวาง) ไฟล์ลงในโครงการของคุณหากคุณไม่ได้ใช้เฟรมเวิร์กแอนิเมชันของ Spring อยู่แล้ว
  2. ในสตอรี่บอร์ดของคุณสร้างข้อ จำกัด ด้านล่างสำหรับวัตถุ / มุมมอง / ฟิลด์ข้อความเลือกข้อ จำกัด (ดับเบิลคลิกที่มัน) และในตัวตรวจสอบตัวตนเปลี่ยนคลาสจาก NSLayoutConstraint เป็น KeyboardLayoutConstraint
  3. ทำ!

วัตถุจะเลื่อนขึ้นโดยอัตโนมัติโดยใช้แป้นพิมพ์พร้อมกัน


2
สุดยอดทางออก! แต่คุณต้องการพื้นที่ปลอดภัยด้านล่างเป็นรายการแรกในข้อ จำกัด (ใช้งานไม่ได้สำหรับฉันเมื่อมันเป็นรายการที่สอง) และทำงานได้ดีที่สุดกับค่าคงที่ที่ตั้งไว้ที่ 0 เนื่องจากมันรักษาค่าคงที่และปรับค่าได้ดีกว่าเพียงแค่เคลื่อนย้ายมันให้ไกลพอที่จะแสดงฟิลด์และคีย์บอร์ด
Mythlandia

คุณมี KeyboardLayoutConstraint รุ่น swift4 หรือไม่
jeet.chanchawat

6

ฉันสร้างโปรโตคอล Swift 3 เพื่อจัดการกับลักษณะที่ปรากฏของคีย์บอร์ด / การหายตัวไป

import UIKit

protocol KeyboardHandler: class {

var bottomConstraint: NSLayoutConstraint! { get set }

    func keyboardWillShow(_ notification: Notification)
    func keyboardWillHide(_ notification: Notification)
    func startObservingKeyboardChanges()
    func stopObservingKeyboardChanges()
}


extension KeyboardHandler where Self: UIViewController {

    func startObservingKeyboardChanges() {

        // NotificationCenter observers
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: nil) { [weak self] notification in
          self?.keyboardWillShow(notification)
        }

        // Deal with rotations
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil, queue: nil) { [weak self] notification in
          self?.keyboardWillShow(notification)
        }

        // Deal with keyboard change (emoji, numerical, etc.)
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextInputCurrentInputModeDidChange, object: nil, queue: nil) { [weak self] notification in
          self?.keyboardWillShow(notification)
        }

        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: nil) { [weak self] notification in
          self?.keyboardWillHide(notification)
        }
    }


    func keyboardWillShow(_ notification: Notification) {

      let verticalPadding: CGFloat = 20 // Padding between the bottom of the view and the top of the keyboard

      guard let value = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
      let keyboardHeight = value.cgRectValue.height

      // Here you could have more complex rules, like checking if the textField currently selected is actually covered by the keyboard, but that's out of this scope.
      self.bottomConstraint.constant = keyboardHeight + verticalPadding

      UIView.animate(withDuration: 0.1, animations: { () -> Void in
          self.view.layoutIfNeeded()
      })
  }


  func keyboardWillHide(_ notification: Notification) {
      self.bottomConstraint.constant = 0

      UIView.animate(withDuration: 0.1, animations: { () -> Void in
          self.view.layoutIfNeeded()
      })
  }


  func stopObservingKeyboardChanges() {
      NotificationCenter.default.removeObserver(self)
  }

}

จากนั้นเพื่อนำไปใช้ใน UIViewController ทำต่อไปนี้:

  • ให้ viewController เป็นไปตามโปรโตคอลนี้:

    class FormMailVC: UIViewControlle, KeyboardHandler {
  • เริ่มสังเกตการเปลี่ยนแปลงของแป้นพิมพ์ใน viewWillAppear:

    // MARK: - View controller life cycle
    override func viewWillAppear(_ animated: Bool) {
      super.viewWillAppear(animated)
      startObservingKeyboardChanges()
    }
  • หยุดการสังเกตการเปลี่ยนแปลงของแป้นพิมพ์ใน viewWillDisappear:

    override func viewWillDisappear(_ animated: Bool) {
      super.viewWillDisappear(animated)
      stopObservingKeyboardChanges()
    }
  • สร้าง IBOutlet สำหรับข้อ จำกัด ด้านล่างจากกระดานเรื่องราว:

    // NSLayoutConstraints
    @IBOutlet weak var bottomConstraint: NSLayoutConstraint!

    (ฉันขอแนะนำให้ฝัง UI ทั้งหมดของคุณไว้ใน "contentView" และการเชื่อมโยงไปยังสถานที่ให้บริการนี้เป็นข้อ จำกัด ด้านล่างจาก contentView นี้ไปยังคู่มือการจัดวางด้านล่าง) ข้อ จำกัด ด้านล่างดูเนื้อหา

  • เปลี่ยนลำดับความสำคัญของข้อ จำกัด ของข้อ จำกัด ด้านบนเป็น 250 (ต่ำ)

ข้อ จำกัด ด้านบนของการดูเนื้อหา

นี่คือการให้มุมมองเนื้อหาทั้งหมดเลื่อนขึ้นเมื่อแป้นพิมพ์ปรากฏขึ้น ลำดับความสำคัญจะต้องต่ำกว่าลำดับความสำคัญข้อ จำกัด อื่น ๆ ในการดูย่อยรวมถึงลำดับความสำคัญของการกอดเนื้อหา / ลำดับความต้านทานการบีบอัดเนื้อหา

  • ตรวจสอบให้แน่ใจว่า Autolayout ของคุณมีข้อ จำกัด เพียงพอที่จะกำหนดว่า contentView ควรเลื่อนขึ้นอย่างไร

คุณอาจต้องเพิ่มข้อ จำกัด "มากกว่า" สำหรับสิ่งนี้: ข้อ จำกัด "มากกว่าที่เท่ากับ"

และที่นี่คุณไป! ไม่มีคีย์บอร์ด

ด้วยคีย์บอร์ด


มันทำงานได้ถ้าคุณใส่ "Relation = Equal" ด้วยโดยไม่มีคำเตือน
Valtoni Boaventura

หากคุณใส่ความสัมพันธ์ที่เท่าเทียมกันมันอาจใช้ได้เฉพาะในสถานการณ์ที่เฉพาะเจาะจงเท่านั้น ในที่อื่นคุณอาจมีคำเตือนรูปแบบอัตโนมัติที่ไม่สอดคล้องกัน ขึ้นอยู่กับเลย์เอาต์ของคุณเอง นั่นเป็นเหตุผลที่ฉันพูดว่า "คุณอาจต้อง"
Frédéric Adda

ตกลงFrédéricตกลง เป็นทางออกที่ดี!
Valtoni Boaventura

หายไปimport UIKit
Mirko

6

UIViewController ส่วนขยายที่เรียบง่ายดังกล่าวสามารถใช้งานได้

//MARK: - Observers
extension UIViewController {

    func addObserverForNotification(notificationName: String, actionBlock: (NSNotification) -> Void) {
        NSNotificationCenter.defaultCenter().addObserverForName(notificationName, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: actionBlock)
    }

    func removeObserver(observer: AnyObject, notificationName: String) {
        NSNotificationCenter.defaultCenter().removeObserver(observer, name: notificationName, object: nil)
    }
}

//MARK: - Keyboard observers
extension UIViewController {

    typealias KeyboardHeightClosure = (CGFloat) -> ()

    func addKeyboardChangeFrameObserver(willShow willShowClosure: KeyboardHeightClosure?,
        willHide willHideClosure: KeyboardHeightClosure?) {
            NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardWillChangeFrameNotification,
                object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { [weak self](notification) in
                    if let userInfo = notification.userInfo,
                        let frame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue(),
                        let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double,
                        let c = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? UInt,
                        let kFrame = self?.view.convertRect(frame, fromView: nil),
                        let kBounds = self?.view.bounds {

                            let animationType = UIViewAnimationOptions(rawValue: c)
                            let kHeight = kFrame.size.height
                            UIView.animateWithDuration(duration, delay: 0, options: animationType, animations: {
                                if CGRectIntersectsRect(kBounds, kFrame) { // keyboard will be shown
                                    willShowClosure?(kHeight)
                                } else { // keyboard will be hidden
                                    willHideClosure?(kHeight)
                                }
                                }, completion: nil)
                    } else {
                            print("Invalid conditions for UIKeyboardWillChangeFrameNotification")
                    }
            })
    }

    func removeKeyboardObserver() {
        removeObserver(self, notificationName: UIKeyboardWillChangeFrameNotification)
    }
}

ตัวอย่างการใช้งาน

override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        removeKeyboardObserver()
    }

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

    addKeyboardChangeFrameObserver(willShow: { [weak self](height) in
        //Update constraints here
        self?.view.setNeedsUpdateConstraints()
        }, willHide: { [weak self](height) in
        //Reset constraints here
        self?.view.setNeedsUpdateConstraints()
    })
}

โซลูชัน Swift 4

//MARK: - Observers
extension UIViewController {

  func addObserverForNotification(_ notificationName: Notification.Name, actionBlock: @escaping (Notification) -> Void) {
    NotificationCenter.default.addObserver(forName: notificationName, object: nil, queue: OperationQueue.main, using: actionBlock)
  }

  func removeObserver(_ observer: AnyObject, notificationName: Notification.Name) {
    NotificationCenter.default.removeObserver(observer, name: notificationName, object: nil)
  }
}

//MARK: - Keyboard handling
extension UIViewController {

  typealias KeyboardHeightClosure = (CGFloat) -> ()

  func addKeyboardChangeFrameObserver(willShow willShowClosure: KeyboardHeightClosure?,
                                      willHide willHideClosure: KeyboardHeightClosure?) {
    NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillChangeFrame,
                                           object: nil, queue: OperationQueue.main, using: { [weak self](notification) in
                                            if let userInfo = notification.userInfo,
                                              let frame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
                                              let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double,
                                              let c = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? UInt,
                                              let kFrame = self?.view.convert(frame, from: nil),
                                              let kBounds = self?.view.bounds {

                                              let animationType = UIViewAnimationOptions(rawValue: c)
                                              let kHeight = kFrame.size.height
                                              UIView.animate(withDuration: duration, delay: 0, options: animationType, animations: {
                                                if kBounds.intersects(kFrame) { // keyboard will be shown
                                                  willShowClosure?(kHeight)
                                                } else { // keyboard will be hidden
                                                  willHideClosure?(kHeight)
                                                }
                                              }, completion: nil)
                                            } else {
                                              print("Invalid conditions for UIKeyboardWillChangeFrameNotification")
                                            }
    })
  }

  func removeKeyboardObserver() {
    removeObserver(self, notificationName: NSNotification.Name.UIKeyboardWillChangeFrame)
  }
}

สวิฟท์ 4.2

//MARK: - Keyboard handling
extension UIViewController {

    func addObserverForNotification(_ notificationName: Notification.Name, actionBlock: @escaping (Notification) -> Void) {
        NotificationCenter.default.addObserver(forName: notificationName, object: nil, queue: OperationQueue.main, using: actionBlock)
    }

    func removeObserver(_ observer: AnyObject, notificationName: Notification.Name) {
        NotificationCenter.default.removeObserver(observer, name: notificationName, object: nil)
    }

    typealias KeyboardHeightClosure = (CGFloat) -> ()

    func removeKeyboardObserver() {
        removeObserver(self, notificationName: UIResponder.keyboardWillChangeFrameNotification)
    }

    func addKeyboardChangeFrameObserver(willShow willShowClosure: KeyboardHeightClosure?,
                                        willHide willHideClosure: KeyboardHeightClosure?) {
        NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillChangeFrameNotification,
                                               object: nil, queue: OperationQueue.main, using: { [weak self](notification) in
                                                if let userInfo = notification.userInfo,
                                                    let frame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
                                                    let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double,
                                                    let c = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt,
                                                    let kFrame = self?.view.convert(frame, from: nil),
                                                    let kBounds = self?.view.bounds {

                                                    let animationType = UIView.AnimationOptions(rawValue: c)
                                                    let kHeight = kFrame.size.height
                                                    UIView.animate(withDuration: duration, delay: 0, options: animationType, animations: {
                                                        if kBounds.intersects(kFrame) { // keyboard will be shown
                                                            willShowClosure?(kHeight)
                                                        } else { // keyboard will be hidden
                                                            willHideClosure?(kHeight)
                                                        }
                                                    }, completion: nil)
                                                } else {
                                                    print("Invalid conditions for UIKeyboardWillChangeFrameNotification")
                                                }
        })
    }
}

2
อื่น ๆ อีกมากมาย "สวิฟท์" กว่าโซลูชั่นอื่น ๆ / ทำงาน / นำมาใช้ใหม่ที่ดีในทุกควบคุมโดยไม่ต้องเขียนใหม่ทุกอย่าง -> แน่นอนหนึ่งที่ดีที่สุดที่นี่ :)
Tib

ฉันพยายาม แต่ไม่มีโอกาส UIScrollView จำเป็นหรือไม่
erdemgc

@erdemgc คุณเห็นตัวอย่างการใช้งานหรือไม่ สิ่งที่คุณต้องการเพียงแค่ UIViewControlller + addKeyboardChangeFrameObserver จากนั้นอย่าลืมที่จะลบมัน
ale_stro

removeKeyboardObserver()วิธีการที่นี่ไม่จริงเอาสังเกตการณ์ หากคุณไม่เรียกสิ่งนี้คุณจะเห็น a Invalid conditions for UIKeyboardWillChangeFrameNotificationในคอนโซลจากเมธอด add หากคุณเรียกสิ่งนี้คุณจะเห็นข้อผิดพลาดเดียวกันซึ่งหมายความว่าผู้สังเกตการณ์จะไม่ถูกลบ เอกสารอธิบายสถานะ "เมื่อต้องการยกเลิกการลงทะเบียนการสังเกตคุณส่งผ่านวัตถุที่ส่งคืนโดยวิธีนี้ไปยังremoveObserver(_:)" ดังนั้นสิ่งที่คุณทำคือบันทึกวัตถุที่ส่งคืนโดยวิธีการนั้นจากนั้นส่งต่อเมื่อคุณต้องการลบผู้สังเกตการณ์
Huy-Anh Hoang

ที่จริงแล้วเมื่อโหลด scrollview แล้วจะมีการกำหนดค่าขอบเขตและคุณไม่สามารถตรวจพบว่าแป้นพิมพ์จะถูกซ่อนหรือไม่หากกรอบของแป้นพิมพ์ตัดกับขอบ
James Kim

5

คุณสามารถใช้ไลบรารีนี้และโค้ดเพียงหนึ่งบรรทัดใน appDidFinishedLaunching และคุณเสร็จแล้ว ..

func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    IQKeyboardManager.sharedManager().enable = true
    return true
}

IQKeyboardManager - ปรับมุมมองเมื่อใดก็ตามที่แป้นพิมพ์ปรากฏลิงก์ - https://github.com/hackiftekhar/IQKeyboardManager


4
struct MoveKeyboard {
    static let KEYBOARD_ANIMATION_DURATION : CGFloat = 0.3
    static let MINIMUM_SCROLL_FRACTION : CGFloat = 0.2;
    static let MAXIMUM_SCROLL_FRACTION : CGFloat = 0.8;
    static let PORTRAIT_KEYBOARD_HEIGHT : CGFloat = 216;
    static let LANDSCAPE_KEYBOARD_HEIGHT : CGFloat = 162;
}


  func textFieldDidBeginEditing(textField: UITextField) {
    let textFieldRect : CGRect = self.view.window!.convertRect(textField.bounds, fromView: textField)
    let viewRect : CGRect = self.view.window!.convertRect(self.view.bounds, fromView: self.view)

    let midline : CGFloat = textFieldRect.origin.y + 0.5 * textFieldRect.size.height
    let numerator : CGFloat = midline - viewRect.origin.y - MoveKeyboard.MINIMUM_SCROLL_FRACTION * viewRect.size.height
    let denominator : CGFloat = (MoveKeyboard.MAXIMUM_SCROLL_FRACTION - MoveKeyboard.MINIMUM_SCROLL_FRACTION) * viewRect.size.height
    var heightFraction : CGFloat = numerator / denominator

    if heightFraction < 0.0 {
        heightFraction = 0.0
    } else if heightFraction > 1.0 {
        heightFraction = 1.0
    }

    let orientation : UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
    if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown) {
        animateDistance = floor(MoveKeyboard.PORTRAIT_KEYBOARD_HEIGHT * heightFraction)
    } else {
        animateDistance = floor(MoveKeyboard.LANDSCAPE_KEYBOARD_HEIGHT * heightFraction)
    }

    var viewFrame : CGRect = self.view.frame
    viewFrame.origin.y -= animateDistance

    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION))

    self.view.frame = viewFrame

    UIView.commitAnimations()
}


func textFieldDidEndEditing(textField: UITextField) {
    var viewFrame : CGRect = self.view.frame
    viewFrame.origin.y += animateDistance

    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)

    UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION))

    self.view.frame = viewFrame

    UIView.commitAnimations()

}

และสุดท้ายเนื่องจากเราใช้วิธีผู้ได้รับมอบหมาย

func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

refactored จากการใช้ purpose-c http://www.cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html


วิธีแก้ปัญหานี้ใช้งานได้สำหรับฉันแม้ว่าฉันจะต้องทำงานเพิ่มเติม: ประกาศvar animateDistance: CGFloat!บวกที่ฉันต้องจัดการ UIKeyboardWillHideNotification เมื่อผู้ใช้กดปุ่มซ่อนแป้นพิมพ์
Rhuantavan

4

โซลูชันอื่นที่ไม่ขึ้นอยู่กับการชำระอัตโนมัติข้อ จำกัด หรือร้านค้าใด ๆ สิ่งที่คุณต้องการคือฟิลด์ของคุณใน scrollview

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "makeSpaceForKeyboard:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "makeSpaceForKeyboard:", name: UIKeyboardWillHideNotification, object: nil)
}

func makeSpaceForKeyboard(notification: NSNotification) {
    let info = notification.userInfo!
    let keyboardHeight:CGFloat = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size.height
    let duration:Double = info[UIKeyboardAnimationDurationUserInfoKey] as! Double

    if notification.name == UIKeyboardWillShowNotification {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            var frame = self.view.frame
            frame.size.height = frame.size.height - keyboardHeight
            self.view.frame = frame
        })
    } else {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            var frame = self.view.frame
            frame.size.height = frame.size.height + keyboardHeight
            self.view.frame = frame
        })
    }

}

1
มันแสดงหน้าจอสีดำหลังจากUIKeyboardWillShowNotificationเรียก
Sachin Kumaram

4

นี่คือเวอร์ชั่นของฉันสำหรับโซลูชันสำหรับ Swift 2.2:

ลงทะเบียนครั้งแรกสำหรับการแสดงคีย์บอร์ด / ซ่อนการแจ้งเตือน

NSNotificationCenter.defaultCenter().addObserver(self,
                                                 selector: #selector(MessageThreadVC.keyboardWillShow(_:)),
                                                 name: UIKeyboardWillShowNotification,
                                                 object: nil)
NSNotificationCenter.defaultCenter().addObserver(self,
                                                 selector: #selector(MessageThreadVC.keyboardWillHide(_:)),
                                                 name: UIKeyboardWillHideNotification,
                                                 object: nil)

จากนั้นในวิธีการที่สอดคล้องกับการแจ้งเตือนเหล่านั้นย้ายมุมมองหลักขึ้นหรือลง

func keyboardWillShow(sender: NSNotification) {
if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
  self.view.frame.origin.y = -keyboardSize.height
  }
}

func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y = 0
}

เคล็ดลับอยู่ในส่วน "keyboardWillShow" ที่รับสายทุกครั้งที่ "QuickType Suggestion Bar" ถูกขยายหรือยุบ จากนั้นเราจะตั้งค่าพิกัด y ของมุมมองหลักซึ่งเท่ากับค่าลบของความสูงของแป้นพิมพ์ทั้งหมด (มีหรือไม่มีส่วน "แถบ QuickType")

ในตอนท้ายอย่าลืมลบผู้สังเกตการณ์

deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}

3

ต่อไปนี้เป็นวิธีแก้ไขปัญหาง่ายๆโดยฟิลด์ข้อความมีข้อ จำกัด ที่ผูกไว้กับแนวทางเค้าโครงด้านล่าง เพียงเพิ่มความสูงของแป้นพิมพ์ลงในค่าคงที่ของข้อ จำกัด

// This constraint ties the text field to the bottom layout guide
@IBOutlet var textFieldToBottomLayoutGuideConstraint: NSLayoutConstraint!

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name:UIKeyboardWillHideNotification, object: nil);
}

func keyboardWillShow(sender: NSNotification) {
    if let keyboardSize = (sender.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.textFieldToBottomLayoutGuideConstraint?.constant += keyboardSize.height
    }
}

func keyboardWillHide(sender: NSNotification) {
    if let keyboardSize = (sender.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.textFieldToBottomLayoutGuideConstraint?.constant -= keyboardSize.height
    }
}

3

ฉันคิดว่าฉันอาจจะสายเกินไป แต่ฉันก็ได้พบคำตอบง่ายๆของ Saqib อีกฉบับ ฉันใช้ Autolayout พร้อมข้อ จำกัด ฉันมีมุมมองเล็ก ๆ ภายในมุมมองหลักอื่นที่มีฟิลด์ชื่อผู้ใช้และรหัสผ่าน แทนที่จะเปลี่ยนพิกัด y ของมุมมองฉันกำลังบันทึกค่าข้อ จำกัด ดั้งเดิมในตัวแปรและเปลี่ยนค่าคงที่ของข้อ จำกัด เป็นค่าบางค่าและอีกครั้งหลังจากแป้นพิมพ์ถูกยกเลิกฉันตั้งค่าข้อ จำกัด ให้เป็นค่าดั้งเดิม วิธีนี้จะช่วยหลีกเลี่ยงปัญหาที่คำตอบของ Saqib ได้รับ (มุมมองยังคงเคลื่อนที่ต่อไปและไม่หยุด) ด้านล่างเป็นรหัสของฉัน ...

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
    self.originalConstraint = self.centerYConstraint.constant
  }

  func keyboardWillShow(sender: NSNotification) {
    self.centerYConstraint.constant += 30
  }

  func keyboardWillHide(sender: NSNotification) {
    self.centerYConstraint.constant = self.originalConstraint
  }

ภายใน keyboardWillShowวิธีการตรวจสอบเงื่อนไขถ้า self.centerYConstraint.constant == self.originalCenterYConstraintแล้วมีหนึ่งบรรทัดของรหัสในระหว่างเงื่อนไขนี้ OriginalCenterYContraint เป็นค่าดั้งเดิมของ centerYContraint ที่ฉันเก็บไว้ใน viewdidload สิ่งนี้ใช้ได้สำหรับฉัน
Sashi

3

Swift 4.x answer, รวมคำตอบจาก @Joseph Lord และ @Isuru bottomConstraintแสดงถึงข้อ จำกัด ด้านล่างของมุมมองที่คุณสนใจในการเคลื่อนไหว

override func viewDidLoad() {
    // Call super
    super.viewDidLoad()

    // Subscribe to keyboard notifications
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(keyboardNotification(notification:)),
                                           name: UIResponder.keyboardWillChangeFrameNotification,
                                           object: nil)        
}


deinit {
    NotificationCenter.default.removeObserver(self)
}


@objc func keyboardNotification(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        // Get keyboard frame
        let keyboardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

        // Set new bottom constraint constant
        let bottomConstraintConstant = keyboardFrame.origin.y >= UIScreen.main.bounds.size.height ? 0.0 : keyboardFrame.size.height

        // Set animation properties
        let duration = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
        let animationCurve = UIView.AnimationOptions(rawValue: animationCurveRaw)

        // Animate the view you care about
        UIView.animate(withDuration: duration, delay: 0, options: animationCurve, animations: {
            self.bottomConstraint.constant = bottomConstraintConstant
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}

2

ฉันทำตามวิธีต่อไปนี้แล้ว:

สิ่งนี้มีประโยชน์เมื่อมีการดู TextView Superview

class AdminLoginViewController: UIViewController,
UITextFieldDelegate{

    @IBOutlet weak var txtUserName: UITextField!
    @IBOutlet weak var txtUserPassword: UITextField!
    @IBOutlet weak var btnAdminLogin: UIButton!

    private var activeField : UIView?

    var param:String!
    var adminUser : Admin? = nil
    var kbHeight: CGFloat!

    override func viewDidLoad()
    {
        self.addKeyBoardObserver()
        self.addGestureForHideKeyBoard()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func addGestureForHideKeyBoard()
    {
        let tapGesture = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard"))
        tapGesture.cancelsTouchesInView = false
        view.addGestureRecognizer(tapGesture)
    }

    func hideKeyboard() {
        self.view.endEditing(true)
    }

    func addKeyBoardObserver(){

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "willChangeKeyboardFrame:",
name:UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "willChangeKeyboardFrame:",
name:UIKeyboardWillHideNotification, object: nil)
    }

    func removeObserver(){
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    //MARK:- textfiled Delegate

    func textFieldShouldBeginEditing(textField: UITextField) -> Bool
    {
         activeField = textField

        return true
    }
    func textFieldShouldEndEditing(textField: UITextField) -> Bool
    {
        if activeField == textField
        {
            activeField = nil
        }

        return true
    }

    func textFieldShouldReturn(textField: UITextField) -> Bool {

        if txtUserName == textField
        {
            txtUserPassword.becomeFirstResponder()
        }
        else if (textField == txtUserPassword)
        {
            self.btnAdminLoginAction(nil)
        }
        return true;
    }

    func willChangeKeyboardFrame(aNotification : NSNotification)
    {
       if self.activeField != nil && self.activeField!.isFirstResponder()
    {
        if let keyboardSize =  (aNotification.userInfo![UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
        {
            let dy = (self.activeField?.superview?.convertRect((self.activeField?.frame)!, toView: view).origin.y)!

            let height = (self.view.frame.size.height - keyboardSize.size.height)

            if dy > height
            {
                var frame = self.view.frame

                frame.origin.y = -((dy - height) + (self.activeField?.frame.size.height)! + 20)

                self.view.frame = frame
            }
        }
    }
    else
    {
        var frame = self.view.frame
        frame.origin.y = 0
        self.view.frame = frame
    }
    } }

2
    func registerForKeyboardNotifications(){
        //Keyboard
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWasShown), name: UIKeyboardDidShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillBeHidden), name: UIKeyboardDidHideNotification, object: nil)


    }
    func deregisterFromKeyboardNotifications(){

        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)

    }
    func keyboardWasShown(notification: NSNotification){

        let userInfo: NSDictionary = notification.userInfo!
        let keyboardInfoFrame = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue()

        let windowFrame:CGRect = (UIApplication.sharedApplication().keyWindow!.convertRect(self.view.frame, fromView:self.view))

        let keyboardFrame = CGRectIntersection(windowFrame, keyboardInfoFrame!)

        let coveredFrame = UIApplication.sharedApplication().keyWindow!.convertRect(keyboardFrame, toView:self.view)

        let contentInsets = UIEdgeInsetsMake(0, 0, (coveredFrame.size.height), 0.0)
        self.scrollViewInAddCase .contentInset = contentInsets;
        self.scrollViewInAddCase.scrollIndicatorInsets = contentInsets;
        self.scrollViewInAddCase.contentSize = CGSizeMake((self.scrollViewInAddCase.contentSize.width), (self.scrollViewInAddCase.contentSize.height))

    }
    /**
     this method will fire when keyboard was hidden

     - parameter notification: contains keyboard details
     */
    func keyboardWillBeHidden (notification: NSNotification) {

        self.scrollViewInAddCase.contentInset = UIEdgeInsetsZero
        self.scrollViewInAddCase.scrollIndicatorInsets = UIEdgeInsetsZero

    }

1
ใช้โค้ดด้านบนเพื่อย้ายฟิลด์ข้อความด้านบนของคีย์บอร์ดใน swift 2.2 มันจะทำงานได้ดี ฉันหวังว่ามันจะช่วยให้ใครบางคน
Kamalkumar.E

1

ฉันได้ทำในลักษณะต่อไปนี้:

class SignInController: UIViewController , UITextFieldDelegate {

@IBOutlet weak var scrollView: UIScrollView!

// outlet declartion
@IBOutlet weak var signInTextView: UITextField!

var kbHeight: CGFloat!

/**
*
* @method viewDidLoad
*
*/

override func viewDidLoad() {
    super.viewDidLoad()

    self.signInTextView.delegate = self

}// end viewDidLoad

/**
*
* @method viewWillAppear
*
*/

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

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)

}// end viewWillAppear

/**
*
* @method viewDidAppear
*
*/

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)


}// end viewDidAppear

/**
*
* @method viewWillDisappear
*
*/
override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

/**
*
* @method textFieldShouldReturn
* retun the keyboard value
*
*/

// MARK -
func textFieldShouldReturn(textField: UITextField) -> Bool {
    signInTextView.resignFirstResponder()
    return true;

}// end textFieldShouldReturn

// MARK - keyboardWillShow
func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        if let keyboardSize =  (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            kbHeight = keyboardSize.height
            self.animateTextField(true)
        }
    }
}// end keyboardWillShow

// MARK - keyboardWillHide
func keyboardWillHide(notification: NSNotification) {
    self.animateTextField(false)
}// end keyboardWillHide

// MARK - animateTextField
func animateTextField(up: Bool) {
    var movement = (up ? -kbHeight : kbHeight)

    UIView.animateWithDuration(0.3, animations: {
        self.view.frame = CGRectOffset(self.view.frame, 0, movement)
    })
}// end animateTextField

/**
*
* @method didReceiveMemoryWarning
*
*/

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.

}// end didReceiveMemoryWarning


}// end SignInController

1

หากคุณเป็นเหมือนฉันที่ได้ลองใช้วิธีแก้ไขปัญหาทั้งหมดข้างต้นแล้วและปัญหาของคุณยังไม่ได้รับการแก้ไขฉันมีวิธีแก้ไขปัญหาที่ยอดเยี่ยมสำหรับคุณที่ใช้งานได้ดี ครั้งแรกฉันต้องการชี้แจงบางสิ่งเกี่ยวกับโซลูชันบางอย่างที่ได้กล่าวไว้

  1. ในกรณีของฉัน IQkeyboardmanager ทำงานเฉพาะเมื่อไม่มีการจัดวางอัตโนมัติในองค์ประกอบหากมีการใช้งานแล้ว IQkeyboard manager จะไม่ทำงานอย่างที่เราคิด
  2. สิ่งเดียวกันกับการเคลื่อนไหวขึ้นของself.view
  3. ฉันมี wriiten ส่วนหัว c วัตถุประสงค์ด้วยการสนับสนุนอย่างรวดเร็วสำหรับการผลักดัน UITexfield ขึ้นไปเมื่อผู้ใช้คลิกที่มันแก้ปัญหาของแป้นพิมพ์ที่ครอบคลุม UITextfield: https://github.com/coolvasanth/smart_keyboard https://github.com/coolvasanth/smart_keyboard
  4. ผู้ที่มีระดับกลางหรือสูงกว่าในการพัฒนาแอพ iOS สามารถเข้าใจพื้นที่เก็บข้อมูลและนำไปใช้งานได้อย่างง่ายดาย ทั้งหมดที่ดีที่สุด

1

นี่คือทางออกทั่วไปสำหรับทุกขั้นตอน TextField -

1) สร้าง ViewController ทั่วไปที่ขยายโดย ViewControllers อื่น

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)

}
 @objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= getMoveableDistance(keyboarHeight: keyboardSize.height)
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}
deinit {
    NotificationCenter.default.removeObserver(self)
}

//get the distance to move up the main view for the focus textfiled
func getMoveableDistance(keyboarHeight : CGFloat) ->  CGFloat{
    var y:CGFloat = 0.0
    if let activeTF = getSelectedTextField(){
        var tfMaxY = activeTF.frame.maxY
        var containerView = activeTF.superview!
        while containerView.frame.maxY != self.view.frame.maxY{
            let contViewFrm = containerView.convert(activeTF.frame, to: containerView.superview)
            tfMaxY = tfMaxY + contViewFrm.minY
            containerView = containerView.superview!
        }
        let keyboardMinY = self.view.frame.height - keyboarHeight
        if tfMaxY > keyboardMinY{
            y = (tfMaxY - keyboardMinY) + 10.0
        }
    }

    return y
}

2) สร้างส่วนขยายของ UIViewController และ TextField ที่ใช้งานอยู่ในปัจจุบัน

//get active text field

ส่วนขยาย UIViewController {func getSelectedTextField () -> UITextField? {

    let totalTextFields = getTextFieldsInView(view: self.view)

    for textField in totalTextFields{
        if textField.isFirstResponder{
            return textField
        }
    }

    return nil

}

func getTextFieldsInView(view: UIView) -> [UITextField] {

    var totalTextFields = [UITextField]()

    for subview in view.subviews as [UIView] {
        if let textField = subview as? UITextField {
            totalTextFields += [textField]
        } else {
            totalTextFields += getTextFieldsInView(view: subview)
        }
    }

    return totalTextFields
}

}


ด้วยเหตุผลบางอย่างฉันมีปัญหาในฟังก์ชั่น keyboardWillShow, keyboardSize ก็เริ่มมีขนาดไม่ถูกต้องหลังจากสลับแป้นพิมพ์ครั้งแรก (สลับแรกมีกรอบที่ถูกต้อง) ฉันแก้ไขสิ่งนี้ด้วยการเปลี่ยนเป็น Guard ให้ userInfo = notification.userInfo อื่น ๆ {return} Guard ให้ keyboardSize = userInfo [UIResponder.keyboardFrameEndUserInfoKey] เป็นอย่างไร NSValue อื่น {return} ให้ keyboardFrame = keyboardSize.cgRectValue ถ้า self.view.frame.origin.y == 0 {self.view.frame.origin.y - = getMoveableDistance (keyboarHeight: keyboardFrame.height)} หวังว่าสิ่งนี้จะช่วยได้ ถ้ามีคนมีปัญหาเดียวกัน :)
Youstanzr

1

ง่ายมากและไม่จำเป็นต้องใช้รหัสเพิ่มเติม เพียงเพิ่มpod 'IQKeyboardManagerSwift'ใน podfile ของคุณและในAppDelegateหน้าของคุณเพิ่มรหัสด้านล่าง

import IQKeyboardManagerSwift

และในdidFinishLaunchingWithOptions()ประเภทวิธี

IQKeyboardManager.shared.enable = true

อย่างนั้นแหละ. ตรวจสอบลิงค์วิดีโอนี้เพื่อความเข้าใจที่ดีขึ้นhttps://youtu.be/eOM94K1ZWN8 หวังว่านี่จะช่วยคุณได้


มันใช้งานได้กับ TextView และฉันจะเปลี่ยนชื่อสำหรับคีย์ส่งคืน "เสร็จสิ้น" ได้อย่างไร
tdt kien

ไปที่: - "IQKeyboardManager.m" แทนที่บรรทัดนี้ (หมายเลขบรรทัดที่ 968): - [textField addDoneOnKeyboardWithTextTxtet ": การกระทำของตนเอง: @selector (doneAction :) ควร showPlaceholder: _shouldShowTextFieldPlaceholder ด้วย: การกระทำด้วยตนเอง: @selector (doneAction :) shouldShowPlaceholder: _shouldShowTextFieldPlaceholder]; และยังไม่ได้ลองใช้กับข้อความดูหวังว่านี่จะช่วยคุณได้
Raghib Arshi

1

รหัสที่สมบูรณ์สำหรับการจัดการแป้นพิมพ์

        override func viewWillAppear(_ animated: Bool) {
            NotificationCenter.default.addObserver(self, selector: #selector(StoryMediaVC.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(StoryMediaVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
        }
        override func viewWillDisappear(_ animated: Bool) {
            NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
            NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
        }
        @objc func keyboardWillShow(notification: NSNotification) {
            guard let userInfo = notification.userInfo else {return}
            guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {return}
            let keyboardFrame = keyboardSize.cgRectValue

            if self.view.bounds.origin.y == 0{
                self.view.bounds.origin.y += keyboardFrame.height
            }
        }


        @objc func keyboardWillHide(notification: NSNotification) {
            if self.view.bounds.origin.y != 0 {
                self.view.bounds.origin.y = 0
            }
        }

0

ฉันแก้ไข @Simpa โซลูชันนิดหน่อย .........

override func viewDidLoad() 
{

    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("makeSpaceForKeyboard:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("makeSpaceForKeyboard:"), name:UIKeyboardWillHideNotification, object: nil);
}

deinit{
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

var keyboardIsVisible = false
override func makeSpaceForKeyboard(notification: NSNotification) {

    let info = notification.userInfo!
    let keyboardHeight:CGFloat = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size.height
    let duration:Double = info[UIKeyboardAnimationDurationUserInfoKey] as! Double

    if notification.name == UIKeyboardWillShowNotification && keyboardIsVisible == false{

        keyboardIsVisible = true

        UIView.animateWithDuration(duration, animations: { () -> Void in
            var frame = self.view.frame
            frame.size.height = frame.size.height - keyboardHeight
            self.view.frame = frame
        })

    } else if keyboardIsVisible == true && notification.name == UIKeyboardWillShowNotification{

    }else {
        keyboardIsVisible = false

        UIView.animateWithDuration(duration, animations: { () -> Void in
            var frame = self.view.frame
            frame.size.height = frame.size.height + keyboardHeight
            self.view.frame = frame
        })
    }
}

0

พวกเขาไม่ทำงานเลยและฉันก็ลงเอยด้วยการใช้ชุดเนื้อหาเพื่อย้ายมุมมองของฉันเมื่อแป้นพิมพ์ปรากฏขึ้น

บันทึก:ฉันใช้ UITableView

โซลูชันที่อ้างอิง @ keyboard-content-offsetซึ่งเขียนด้วยวัตถุประสงค์ C ทั้งหมดวิธีการแก้ปัญหาด้านล่างคือ Swift ที่สะอาด

เพิ่มผู้สังเกตการณ์การแจ้งเตือน @ viewDidLoad ()

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(yourClass.keyboardWillBeShown), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(yourClass.keyboardWillBeHidden), name:UIKeyboardWillHideNotification, object: nil);

เพื่อให้ได้ขนาดแป้นพิมพ์อันดับแรกเราจะรับพจนานุกรม userInfo จากวัตถุแจ้งเตือนซึ่งเก็บวัตถุเพิ่มเติมใด ๆ ที่ผู้รับของเราอาจใช้

จากพจนานุกรมนั้นเราสามารถรับวัตถุ CGRect ที่อธิบายเฟรมของแป้นพิมพ์โดยใช้คีย์ UIKeyboardFrameBeginUserInfoKey

ใช้ส่วนแทรกเนื้อหาสำหรับวิธีการดูตาราง @ keyboardWillBeShown

func keyboardWillBeShown(sender: NSNotification)
{        
    // Move the table view

    if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
    {
        let contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.height), 0.0);

        yourTableView.contentInset = contentInsets;

        yourTableView.scrollIndicatorInsets = contentInsets;
    }
}

กู้คืนเมธอด view @ keyboardWillBeHidden

func keyboardWillBeHidden(sender: NSNotification)
{
    // Moving back the table view back to the default position

    yourTableView.contentInset = UIEdgeInsetsZero;

    yourTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}

หากคุณต้องการคำนึงถึงการวางแนวของอุปกรณ์ด้วยให้ใช้ข้อความสั่งแบบมีเงื่อนไขเพื่อปรับแต่งรหัสตามความต้องการของคุณ

// Portrait
UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.height), 0.0);

// Landscape
UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.width), 0.0);

0
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

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

func keyboardWillShow(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
    }
}

func keyboardWillHide(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    }
}

ป้อนคำอธิบายรูปภาพที่นี่


0

โซลูชัน Swift 4 ที่ฉันใช้ใช้ขนาดแป้นพิมพ์ แทนที่serverStatusStackViewด้วยมุมมองที่คุณสนใจเช่นself.view:

deinit {
    NotificationCenter.default.removeObserver(self)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        serverStatusStackView.frame.origin.y = keyboardSize.height * 2 - serverStatusStackView.frame.height
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        serverStatusStackView.frame.origin.y += keyboardSize.height
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.