Di chuyển trường văn bản khi bàn phím xuất hiện nhanh


217

Tôi đang sử dụng Swift để lập trình với iOS và tôi đang sử dụng mã này để di chuyển UITextField, nhưng nó không hoạt động. Tôi gọi hàm keyboardWillShowchính xác, nhưng trường văn bản không di chuyển. Tôi đang sử dụng tính năng tự động thanh toán.

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
Hướng dẫn hướng dẫn với các tệp Dự án: codebeaulieu.com/43/ Mạnh
Dan Beaulieu

Có lẽ deinit và viewDidLoad không cân bằng.
Ricardo

Dựa trên cả tài liệu và kinh nghiệm cá nhân của Apple. Đây là git repo của tôi bằng cách sử dụng UIScrollView để di chuyển TF: github.com/29satnam/MoveTextFieldWhenPalAppearsSwift
Codetard 18/07/17

Câu trả lời:


315

Có một vài cải tiến được thực hiện trên các câu trả lời hiện có.

Đầu tiên, UIKeyboardWillChangeFrameNotification có lẽ là thông báo tốt nhất vì nó xử lý các thay đổi không chỉ hiển thị / ẩn mà thay đổi do thay đổi bàn phím (ngôn ngữ, sử dụng bàn phím của bên thứ 3, v.v.) và xoay cũng vậy (nhưng lưu ý nhận xét bên dưới cho biết bàn phím sẽ ẩn cũng được xử lý để hỗ trợ kết nối bàn phím phần cứng).

Thứ hai, các tham số hoạt hình có thể được kéo từ thông báo để đảm bảo rằng các hoạt ảnh được kết hợp đúng cách.

Có thể có các tùy chọn để dọn sạch mã này hơn một chút, đặc biệt nếu bạn cảm thấy thoải mái với việc hủy mã từ điển.

Swift 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)
    }
}

(Đã chỉnh sửa tài khoản cho bàn phím hoạt hình ngoài màn hình thay vì thu nhỏ, theo nhận xét tuyệt vời của @ Gabox bên dưới)

Swift 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 đẹp. nhưng tôi thấy điều này không hoạt động khi bàn phím bị ẩn vì endFrame?.size.heightkhông phải là con số không. Tôi đã nhận được khung kết thúc như UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 1024}, {768, 264}}";. Chạy trên Trình mô phỏng iPad iOS 8.3, Chân dung. Xcode6.3 beta4.
Hlung 28/03/2015

8
nếu bàn phím không ẩn, hãy thử sử dụng mã này nếu endFrame? .origin.y> = UIScreen.mainScreen (). bound.size.height {self.keyboardHeightLayoutConstraint? .constant = 0.0} khác {self.keyboardHeightLayoutCon. = endFrame.size.height}
Gabriel Goncalves

3
keyBoardHeightLayoutConstraint là một ràng buộc được xác định trong InterfaceBuilder ràng buộc phía dưới của chế độ xem mà bạn muốn di chuyển / thu nhỏ vào hướng dẫn bố cục dưới cùng hoặc dưới cùng của chế độ xem chính cho trình điều khiển khung nhìn. Hằng số ban đầu được đặt thành 0 và sẽ được điều chỉnh để nhường chỗ cho bàn phím khi bàn phím xuất hiện hoặc thay đổi kích thước.
Joseph Lord

2
Lưu ý rằng .UIKeyboardWillChangeFramekhông kích hoạt khi bàn phím phần cứng được kết nối, mặc dù bàn phím iOS biến mất. Bạn cần phải quan sát .UIKeyboardWillHidelà tốt để bắt trường hợp cạnh đó.
jamesk

1
@Sulthan hoạt động ổn .. Vấn đề của tôi là tăng cao hơn một chút so với keybaord. Có cách nào chúng ta có thể khắc phục điều này?
Pavlos

128

Nếu bạn đang sử dụng Bố cục tự động, tôi giả sử bạn đã đặt ràng buộc Không gian dưới cùng thành Superview . Nếu đó là trường hợp, bạn chỉ cần cập nhật giá trị của ràng buộc. Đây là cách bạn làm điều đó với một chút hoạt hình.

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
    })
}

20 mã hóa cứng chỉ được thêm vào để bật trường văn bản phía trên bàn phím một chút. Nếu không, lề trên cùng của bàn phím và lề dưới của trường văn bản sẽ chạm nhau.

Khi bàn phím bị loại bỏ, hãy đặt lại giá trị của ràng buộc về giá trị ban đầu.


1
Bạn có thể giải thích cho tôi xin vui lòng làm thế nào tôi xác định nó? Cảm ơn! tôi luôn kiểm soát tất cả trên bảng phân cảnh
Pedro Manfredi

4
bottomConstraint là tên tôi đặt cho ràng buộc. Tôi đã chọn các hằng số, kéo và tạo một IBOutlet cho nó và đặt tên đó. Bạn có thể tạo IBOutlets để ràng buộc giống như bạn có thể làm với các thành phần UI khác như nút và trường văn bản.
Isuru

2
Câu trả lời này hoạt động rất tốt, ngoại trừ hoạt hình xảy ra ngay lập tức đối với tôi. Kiểm tra làm thế nào để tôi làm thay đổi ràng buộc? để làm thế nào để hoạt hình đúng cách.
Adam Johns

2
@ vinbhai4u Bạn phải đăng ký UIKeyboardWillShowNotificationthông báo. Nhìn vào mã trong câu hỏi của OP.
Isuru

8
@AdamJohns Để tạo hiệu ứng thay đổi ràng buộc, hãy cập nhật hằng số bên ngoài animateWithDurationvà gọi self.view.layoutIfNeeded()bên trong khối animate.
Tối đa

110

Một giải pháp đơn giản là di chuyển chế độ xem lên với hằng số chiều cao bàn phím.

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  
}

Swift 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
Tôi thích giải pháp đơn giản này. Nhưng tôi đã thêm một boolean bàn phím vì tôi đã di chuyển hơn một trường văn bản. Tôi chỉ di chuyển bàn phím một lần trong khi nó đang hiển thị. Cảm ơn.
Ken

2
thay vì di chuyển xem, di chuyển TextView
ericgu

1
Điều này sẽ giữ cho giá trị y của chế độ xem nếu người dùng chuyển đổi ngôn ngữ nhập.
Jeffrey Neo

thay vì thay đổi giá trị self.view tôi đã làm giá trị self.myConstraint, nó hoạt động nhưng điều quan trọng là (chế độ ràng buộc được áp dụng) tiếp tục tăng lên. có ai phải đối mặt với vấn đề này?
Sashi

5
Thay vì sử self.view.frame.origin.y -= 150dụng self.view.frame.origin.y = -150và thay vì self.view.frame.origin.y += 150sử dụng self.view.frame.origin.y = 0. Điều này ngăn tầm nhìn di chuyển 150 mỗi lần chạm vào một trường mới.
gunwin

43

Để di chuyển chế độ xem của bạn trong khi chỉnh sửa trường văn bản, hãy thử điều này, tôi đã áp dụng điều này,

Tùy chọn 1: - ** ** Cập nhật trong Swift 5.0 và iPhone X, XR, XS và XS Max Move bằng NotificationCenter

  • Đăng ký thông báo này trong func viewWillAppear(_ animated: Bool)

  • Deregister Thông báo này trong func viewWillDisappear(_ animated: Bool)

Lưu ý: - Nếu bạn sẽ không hủy đăng ký, nó sẽ gọi từ lớp con và sẽ gây ra sự cố.

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)
    }
}

Cách 2: - Nó hoạt động tốt

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()
}

Tôi đã nhận được câu trả lời này từ nguồn UITextField này di chuyển lên khi bàn phím xuất hiện trong Swift

Ở 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, Cảm ơn bạn đã làm việc chăm chỉ. Nhưng, Nó hoạt động tốt nhất trên iPhone 5,4 và 6. Nhưng, làm thế nào tôi có thể vô hiệu hóa nó trên iPhone 6plus và iPad (cao hơn)
Thiha Aung

Nếu bạn đang sử dụng Tùy chọn 1, vui lòng đảm bảo thêm một ràng buộc IBOutlet. Bạn sẽ tạo một ràng buộc mà bạn muốn thay đổi kích thước bằng cách sử dụng Auto-layout, sau đó kéo và thả nó vào trình điều khiển khung nhìn để tạo một IBOutlet mà tôi tham chiếu nó là self.iboutletConstraint.constant trong hàm animate. Ngoài ra, điều này không điều chỉnh lại ổ cắm khi ẩn bàn phím, tôi đã xử lý điều đó bằng cách đặt lại ràng buộc về giá trị ban đầu của nó.
Hammad Tariq

21

Tôi yêu mã Swift sạch. Vì vậy, đây là mã chặt chẽ nhất mà tôi có thể đưa ra để di chuyển chế độ xem văn bản lên / xuống bằng bàn phím. Hiện tại nó đang hoạt động trong một ứng dụng sản xuất iOS 2/9 Swift 2.

CẬP NHẬT (Tháng 3 năm 2016): Tôi chỉ cần thắt chặt mã trước đó càng nhiều càng tốt. Ngoài ra, có một loạt các câu trả lời phổ biến ở đây mã hóa chiều cao bàn phím và các thông số hoạt hình. Không cần điều đó, chưa kể rằng các số trong các câu trả lời này không phải lúc nào cũng khớp với các giá trị thực tôi đang thấy trên 6s + iOS9 của tôi (chiều cao bàn phím là 226, thời lượng 0,25 và đường cong hoạt hình là 7). Trong mọi trường hợp, hầu như không có mã bổ sung để nhận các giá trị đó trực tiếp từ hệ thống. Xem bên dưới.

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
    )

}

LƯU Ý: Mã này bao gồm hầu hết các bình luận / trường hợp chung. Tuy nhiên, có thể cần nhiều mã hơn để xử lý các hướng khác nhau và / hoặc bàn phím tùy chỉnh Đây là một bài viết chuyên sâu về làm việc với bàn phím iOS. Nếu bạn cần xử lý mọi kịch bản, điều này có thể giúp ích.


Có vẻ là Swift 1.1 và tôi nghĩ sẽ không được biên dịch trong Swift 1.2 vì nó sử dụng ascho các diễn viên bắt buộc. as!có thể hoạt động nhưng như bạn có thể thấy ở những nơi khác trên trang này, tôi tránh ép buộc và ép buộc bản thân mình.
Joseph Lord

Biên dịch ngay trong Swift 1.2. Và tôi đã thêm một nhận xét cho mã lại: việc hủy bỏ bắt buộc. Chúc mừng.
scootermg

Giáo sư. Ý tôi là Swift 2.
scootermg

Tùy thuộc vào cách bạn liên kết lên, baseConstraintnó có thể baseConstraint.constant = moveUp ? keyboardHeight : 0thay vì baseConstraint.constant = moveUp ? -keyboardHeight : 0.
hạn

15

Chỉnh sửa : Tôi đề nghị một giải pháp dễ dàng và sạch sẽ hơn. Chỉ cần thay đổi lớp ràng buộc khoảng cách dưới cùng thành Bàn phímLayoutConstraint . Nó sẽ tự động mở rộng đến chiều cao bàn phím.


Đây là phiên bản cải tiến của câu trả lời của @JosephLord.

Như đã thử nghiệm trên iPad Simulator iOS, Portrait. Xcode6.3 beta4, tôi thấy câu trả lời của ông không làm việc khi bàn phím là lẩn trốn vì UIKeyboardFrameEndUserInfoKey"NSRect: {{0, 1024}, {768, 264}}";. Chiều cao không bao giờ 0.

Điều này quay trở lại để sử dụng truyền thống UIKeyboardWillShowNotificationUIKeyboardWillHideNotificationđể biết rõ hơn khi bàn phím bị ẩn thay vì dựa vào chiều cao của khung cuối. UIKeyboardWillShowNotificationcũng được gửi khi khung bàn phím bị thay đổi, vì vậy nó sẽ bao gồm tất cả các trường hợp sử dụng.

    // 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)
        }
    }

Bạn có thể vui lòng giải thích chỉnh sửa của bạn? Tôi không thể làm cho nó hoạt động. Tôi có một UIScrollView với một nút ở phía dưới. Tôi giải quyết các lớp ở ràng buộc dưới lề trên dưới.
schw4ndi

@ schw4ndi xem các ràng buộc dưới cùng của bạn bị ràng buộc với quan điểm nào? nó nên được kết nối dưới cùng của scrollview với dưới cùng của giám sát của scrollview đó.
Hlung

Ồ cảm ơn, tôi đã có sự ràng buộc giữa nút và scrollView
schw4ndi

9

tôi đang làm việc với swift 4 và tôi đã giải quyết vấn đề này mà không sử dụng bất kỳ ràng buộc dưới cùng nào nữa xem mã của tôi ở đây. Tôi thực sự làm việc với trường hợp của tôi

1) Thêm thông báo quan sát trong tải đã

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) Xóa Thông báo Người quan sát như

deinit {
        NotificationCenter.default.removeObserver(self)
    }

3) Thêm phương thức hiển thị / ẩn bàn phím như

 @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) Thêm đại biểu textfeild và thêm các phương thức TouchBegan .usefull để ẩn bàn phím khi chạm bên ngoài textfeild trên màn hình

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

    }

cần phải cóUIKeyboardFrameEndUserInfoKey
Micro

1
NSNotification.Name.UIKeyboardWillShow được đổi tên thành UIResponder.keyboardWillShowNotificationcũng UIKeyboardFrameBeginUserInfoKey đếnUIResponder.keyboardFrameBeginUserInfoKey
SMJ

7

Đây là phiên bản cải tiến của câu trả lời của @JosephLord và @ Hlung. Nó có thể áp dụng cho dù bạn có thanh tab hay không. Và nó sẽ khôi phục hoàn hảo chế độ xem được di chuyển bằng bàn phím về vị trí ban đầu.

// 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

Cách dễ nhất mà không yêu cầu bất kỳ mã nào:

  1. Tải xuống Bàn phímLayoutConstraint.swift và thêm (kéo và thả) tệp vào dự án của bạn, nếu bạn chưa sử dụng khung hoạt hình Spring.
  2. Trong bảng phân cảnh của bạn, tạo một ràng buộc dưới cùng cho đối tượng / khung nhìn / trường văn bản, chọn ràng buộc (bấm đúp vào nó) và trong Trình kiểm tra danh tính, thay đổi lớp của nó từ NSLayoutConstraint thành KeyboardLayoutConstraint.
  3. Làm xong!

Đối tượng sẽ tự động di chuyển lên bằng bàn phím, đồng bộ hóa.


2
Giải pháp tuyệt vời! Nhưng bạn cần Vùng an toàn.Bottom là mục đầu tiên trong ràng buộc (không hoạt động với tôi khi đó là mục thứ hai). Và nó hoạt động tốt nhất với hằng số được đặt thành 0 vì nó bảo toàn hằng số và điều chỉnh nó, thay vì chỉ di chuyển nó đủ xa để hiển thị trường và bàn phím.
Thần thoại

Bạn có phiên bản Bàn phímLayoutConstraint swift4 không?
jeet.chanchaw

6

Tôi đã tạo một giao thức Swift 3 để xử lý sự xuất hiện / biến mất của bàn phím

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)
  }

}

Sau đó, để triển khai nó trong UIViewControll, hãy làm như sau:

  • hãy để viewControll tuân thủ giao thức này:

    class FormMailVC: UIViewControlle, KeyboardHandler {
  • bắt đầu quan sát những thay đổi của bàn phím trong viewWillAppear:

    // MARK: - View controller life cycle
    override func viewWillAppear(_ animated: Bool) {
      super.viewWillAppear(animated)
      startObservingKeyboardChanges()
    }
  • dừng quan sát thay đổi bàn phím trong viewWillDisappear:

    override func viewWillDisappear(_ animated: Bool) {
      super.viewWillDisappear(animated)
      stopObservingKeyboardChanges()
    }
  • tạo một IBOutlet cho các ràng buộc dưới cùng từ bảng phân cảnh:

    // NSLayoutConstraints
    @IBOutlet weak var bottomConstraint: NSLayoutConstraint!

    (Tôi khuyên bạn nên có tất cả giao diện người dùng của mình được nhúng bên trong "contentView" và liên kết với thuộc tính này ràng buộc dưới cùng từ nội dung này Xem hướng dẫn bố cục dưới cùng) Nội dung giới hạn dưới cùng xem

  • thay đổi mức ưu tiên ràng buộc của ràng buộc hàng đầu thành 250 (thấp)

Nội dung xem hạn chế hàng đầu

Điều này là để cho toàn bộ chế độ xem nội dung trượt lên trên khi bàn phím xuất hiện. Mức độ ưu tiên phải thấp hơn bất kỳ mức độ ưu tiên ràng buộc nào khác trong các cuộc phỏng vấn, bao gồm các ưu tiên ôm nội dung / ưu tiên kháng nén nội dung.

  • Đảm bảo rằng Autolayout của bạn có đủ các ràng buộc để xác định cách xem nội dung.

Bạn có thể phải thêm một ràng buộc "lớn hơn bằng" cho điều này: ràng buộc "lớn hơn bằng"

Và bạn đến đây! Không có bàn phím

Với bàn phím


Nó cũng hoạt động nếu bạn đặt "Relation = Equal" mà không có cảnh báo.
Valtoni Boaventura

Nếu bạn đặt một mối quan hệ bình đẳng, nó có thể chỉ hoạt động trong các tình huống cụ thể. Trong những người khác, bạn có thể có một cảnh báo không nhất quán bố trí tự động. Nó phụ thuộc vào bố cục của riêng bạn. Đó là lý do tại sao tôi nói "bạn có thể phải".
Frédéric Adda

Ok Frédéric, đã đồng ý. Là một giải pháp tốt đẹp!
Valtoni Boaventura

mất tíchimport UIKit
Mirko

6

UIViewController Phần mở rộng đơn giản như vậy có thể được sử dụng

//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)
    }
}

Ví dụ về cách sử dụng

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()
    })
}

Giải pháp 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)
  }
}

Swift 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
"Swift" nhiều hơn các giải pháp khác / hoạt động tuyệt vời / có thể tái sử dụng trong mọi bộ điều khiển mà không cần viết lại mọi thứ -> chắc chắn là giải pháp tốt nhất ở đây :)
Tib

Tôi đã thử nhưng không có cơ hội, UIScrollView có cần thiết hay không?
erdemgc

@erdemgc bạn có thấy Ví dụ về cách sử dụng không? Tất cả những gì bạn cần chỉ là UIViewControlller + addPalChangeFrameObserver và sau đó đừng quên xóa nó
ale_stro

Các removeKeyboardObserver()phương pháp ở đây không thực sự loại bỏ các quan sát viên. Nếu bạn không gọi nó, bạn sẽ thấy một Invalid conditions for UIKeyboardWillChangeFrameNotificationgiao diện điều khiển từ phương thức add. Nếu bạn gọi điều này, bạn sẽ thấy lỗi tương tự, có nghĩa là người quan sát không bị xóa. Tài liệu nêu rõ "Để hủy đăng ký các quan sát, bạn chuyển đối tượng được phương thức này trả về removeObserver(_:)." Vì vậy, những gì bạn làm thay vào đó là lưu đối tượng được trả về bởi phương thức đó, sau đó chuyển nó vào khi bạn muốn loại bỏ trình quan sát.
Huy-Anh Hoàng

Trên thực tế, khi scrollview được tải, ràng buộc được gán một giá trị và bạn không thể phát hiện nếu một bàn phím sẽ bị ẩn nếu khung bàn phím giao nhau với ràng buộc.
James Kim

5

Bạn có thể sử dụng thư viện này và chỉ một dòng mã trong appDidFinishedLaunching và bạn đã hoàn thành ..

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

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

IQPalManager - điều chỉnh chế độ xem bất cứ khi nào bàn phím xuất hiện liên kết - https://github.com/hackiftekhar/IQPalManager


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()

}

Và cuối cùng vì chúng tôi đang sử dụng các phương thức đại biểu

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

tái cấu trúc từ việc sử dụng object-c http://www.cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html


Giải pháp này hiệu quả với tôi, mặc dù tôi phải thực hiện một số công việc bổ sung: khai báo một điểm var animateDistance: CGFloat!cộng tôi phải xử lý UIKeyboardWillHideNotification khi người dùng nhấn nút ẩn bàn phím.
Rhugeavan

4

Một giải pháp khác không phụ thuộc vào tự động thanh toán, các ràng buộc hoặc bất kỳ cửa hàng nào. Những gì bạn cần là (các) lĩnh vực của bạn trong một cuộn xem.

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
Nó hiển thị màn hình đen sau khi UIKeyboardWillShowNotificationđược gọi.
Sachin Kumaram

4

Đây là phiên bản của tôi cho một giải pháp cho Swift 2.2:

Đăng ký đầu tiên cho Hiển thị bàn phím / Ẩn thông báo

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

Sau đó, trong các phương thức coresponding cho các thông báo đó di chuyển khung nhìn chính lên hoặc xuống

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
}

Thủ thuật nằm ở phần "keyboardWillShow" nhận cuộc gọi mỗi khi "Thanh đề xuất QuickType" được mở rộng hoặc thu gọn. Sau đó, chúng tôi luôn đặt tọa độ y của chế độ xem chính bằng với giá trị âm của tổng chiều cao bàn phím (có hoặc không có phần "thanh QuickType").

Cuối cùng, đừng quên loại bỏ các quan sát viên

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

3

Sau đây là một giải pháp đơn giản, theo đó trường văn bản có một ràng buộc buộc nó vào hướng dẫn bố cục dưới cùng. Nó chỉ đơn giản là thêm chiều cao bàn phím vào hằng số ràng buộc.

// 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

Chà, tôi nghĩ rằng tôi có thể đã quá muộn nhưng tôi đã tìm thấy một phiên bản đơn giản khác của câu trả lời của Saqib. Tôi đang sử dụng Autolayout với các ràng buộc. Tôi có một chế độ xem nhỏ bên trong một chế độ xem chính khác với các trường tên người dùng và mật khẩu. Thay vì thay đổi tọa độ y của chế độ xem, tôi đang lưu giá trị ràng buộc ban đầu trong một biến và thay đổi hằng số ràng buộc thành một giá trị và một lần nữa sau khi bàn phím bỏ qua, tôi đang thiết lập ràng buộc thành giá trị ban đầu. Bằng cách này, nó tránh được câu trả lời của Saqib, (Quan điểm tiếp tục di chuyển lên và không dừng lại). Dưới đây là mã của tôi ...

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
  }

Bên trong bàn phím Phương thứcWillShow kiểm tra điều kiện nếu self.centerYConstraint.constant == self.origenCenterYConstraint sau đó có một dòng mã ở giữa điều kiện này. OriginalCenterYContraint là giá trị ban đầu của centreYContraint mà tôi đang lưu trữ trong viewdidload. Điều này làm việc cho tôi.
Sashi

3

Swift 4.x trả lời, hợp nhất câu trả lời từ @Joseph Lord và @Isuru. bottomConstraintđại diện cho hạn chế dưới cùng của chế độ xem mà bạn quan tâm khi di chuyển.

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

Tôi đã thực hiện theo cách sau:

Điều này hữu ích khi màn hình giám sát trường văn bản được xem

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
Sử dụng mã ở trên để di chuyển trường văn bản phía trên bàn phím trong swift 2.2, nó sẽ hoạt động tốt. tôi hy vọng nó sẽ giúp được ai đó
Kamalkumar.E

1

Tôi đã làm theo cách sau:

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

Nếu bạn giống như tôi, người đã thử tất cả các giải pháp trên mà vẫn không giải quyết được vấn đề của bạn, tôi có một giải pháp tuyệt vời cho bạn, nó hoạt động như một cơ duyên. Đầu tiên tôi muốn làm rõ vài điều về một số giải pháp được đề cập ở trên.

  1. Trong trường hợp của tôi, IQkeyboardmanager chỉ hoạt động khi không có bố cục tự động được áp dụng cho các yếu tố, nếu nó được áp dụng thì trình quản lý IQkeyboard sẽ không hoạt động theo cách chúng ta nghĩ.
  2. Điều tương tự với chuyển động đi lên của self.view.
  3. Tôi đã muốn có một tiêu đề c mục tiêu với sự hỗ trợ nhanh chóng để đẩy UITexfield lên trên khi người dùng nhấp vào nó, giải quyết vấn đề bàn phím bao phủ UITextfield: https://github.com/coolvasanth/smart_keyboard .
  4. Một người có trình độ trung cấp trở lên trong phát triển ứng dụng iOS có thể dễ dàng hiểu kho lưu trữ và triển khai nó. Tất cả tốt nhất

1

Đây là một giải pháp chung cho tất cả các Bước của TextField -

1) Tạo một ViewContoder chung được mở rộng bởi các ViewControllers khác

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) Tạo phần mở rộng của UIViewControll và TextField hiện đang hoạt động

//get active text field

tiện ích mở rộng UIViewControll {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
}

}


Vì một số lý do, tôi đã gặp sự cố trong chức năng keyboardWillShow, kích thước bàn phím bị sai kích thước sau khi chuyển đổi bàn phím đầu tiên (lần chuyển đổi đầu tiên có khung chính xác). Tôi đã sửa lỗi này bằng cách thay đổi nó để bảo vệ cho userInfo = notify.userInfo khác {return} Guard let keyboardSize = userInfo [UIResponder.keyboardFrameEndUserInfoKey] là? NSValue khác {return} let keyboardFrame = keyboardSize.cgRectValue if self.view.frame.origin.y == 0 {self.view.frame.origin.y - = getMovizableDistance (keyboarHeight: keyboardFrame.height) nếu ai đó có cùng một vấn đề :)
Youstanzr

1

Rất đơn giản và không cần mã thêm. Chỉ cần thêm pod 'IQKeyboardManagerSwift'vào podfile của bạn và trong AppDelegatetrang của bạn thêm mã bên dưới.

import IQKeyboardManagerSwift

và trong didFinishLaunchingWithOptions()kiểu phương thức

IQKeyboardManager.shared.enable = true

chính là nó kiểm tra liên kết video này để hiểu rõ hơn https://youtu.be/eOM94K1ZWN8 Hy vọng điều này sẽ giúp bạn.


Nó có hoạt động cho TextView không và làm cách nào tôi có thể thay đổi tiêu đề cho khóa trả về "Xong"?
tdt kien

Goto: - "IQ cánh tay quản lý tự hành động: @selector (xongAction :) nênShowPlaceholder: _shouldShowTextFieldPlaceholder]; Và chưa thử cho xem văn bản, hy vọng điều này sẽ giúp bạn.
Raghib Arshi

1

Mã hoàn chỉnh để quản lý bàn phím.

        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

Tôi đã sửa đổi giải pháp @Simpa một chút .........

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

Không ai trong số họ làm việc và cuối cùng tôi đã sử dụng phần nội dung để di chuyển chế độ xem của mình lên khi bàn phím xuất hiện.

Lưu ý: Tôi đã sử dụng UITableView

Giải pháp tham chiếu @ bàn phím-nội dung bù được viết hoàn toàn trong mục tiêu C, giải pháp bên dưới là Swift sạch.

Thêm trình quan sát thông báo @ 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);

Để có được kích thước bàn phím, trước tiên chúng tôi lấy từ điển userInfo từ đối tượng thông báo, nơi lưu trữ bất kỳ đối tượng bổ sung nào mà người nhận của chúng tôi có thể sử dụng.

Từ từ điển đó, chúng ta có thể lấy đối tượng CGRect mô tả khung của bàn phím bằng cách sử dụng khóa UIKeyboardFrameBeginUserInfoKey.

Áp dụng phần chèn nội dung cho chế độ xem bảng @ 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;
    }
}

Khôi phục chế độ xem @ keyboardWillBeHidden

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

    yourTableView.contentInset = UIEdgeInsetsZero;

    yourTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}

Nếu bạn muốn giữ hướng thiết bị cũng được xem xét, hãy sử dụng các câu lệnh có điều kiện để điều chỉnh mã theo nhu cầu của bạn.

// 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)
    }
}

nhập mô tả hình ảnh ở đây


0

Giải pháp Swift 4 tôi sử dụng, có kích thước bàn phím. Thay thế serverStatusStackViewbằng bất kỳ chế độ xem nào bạn quan tâm, ví dụ 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)
}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.