Chỉ di chuyển chế độ xem khi bàn phím bao phủ trường nhập


148

Tôi đang cố gắng xây dựng một màn hình đầu vào cho iPhone. Màn hình có một số trường đầu vào. Hầu hết trong số họ ở trên cùng của màn hình, nhưng hai trường ở phía dưới. Khi người dùng cố gắng chỉnh sửa văn bản ở phía dưới màn hình, bàn phím sẽ bật lên và nó sẽ che màn hình. Tôi đã tìm thấy một giải pháp đơn giản để di chuyển màn hình lên khi điều này xảy ra, nhưng kết quả là màn hình luôn di chuyển lên và các trường trên đỉnh màn hình di chuyển ra khỏi tầm với khi người dùng cố gắng chỉnh sửa chúng.

Có cách nào để màn hình chỉ di chuyển khi các trường dưới cùng được chỉnh sửa không?

Tôi đã sử dụng mã này tôi tìm thấy ở đây :

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

func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}

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

có thể bạn có thể sử dụng func textFieldDidBeginEditing (textField: UITextField!) {} để phát hiện trường văn bản nào đã bắt đầu chỉnh sửa và thực hiện ẩn / hiển thị bàn phím
humblePilgrim

Tôi quên đề cập rằng tôi là người mới sử dụng Swift :( Cú pháp chính xác để kiểm tra điều này là gì (làm thế nào để tôi có được tên trường trong chức năng này?)
John Allijn

Câu trả lời:


211

Vấn đề của bạn được Apple giải thích rõ trong tài liệu này . Mã ví dụ trên trang này (at Listing 4-1) thực hiện chính xác những gì bạn cần, nó sẽ cuộn chế độ xem của bạn chỉ khi chỉnh sửa hiện tại ở dưới bàn phím. Bạn chỉ cần đặt các điều khiển cần thiết của mình trong scrollViiew. Vấn đề duy nhất là đây là Objective-C và tôi nghĩ bạn cần nó trong Swift..so..tất cả là:

Khai báo một biến

var activeField: UITextField?

sau đó thêm các phương thức này

 func registerForKeyboardNotifications()
{
    //Adding notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}


func deregisterFromKeyboardNotifications()
{
    //Removing notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(notification: NSNotification)
{
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.scrollEnabled = true
    var info : NSDictionary = notification.userInfo!
    var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

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


}


func keyboardWillBeHidden(notification: NSNotification)
{
    //Once keyboard disappears, restore original positions
    var info : NSDictionary = notification.userInfo!
    var keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
    var contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.scrollEnabled = false

}

func textFieldDidBeginEditing(textField: UITextField!)
{
    activeField = textField
}

func textFieldDidEndEditing(textField: UITextField!)
{
    activeField = nil
}

Hãy chắc chắn khai báo ViewContoder của bạn UITextFieldDelegatevà đặt các đại biểu chính xác trong các phương thức khởi tạo của bạn: ex:

self.you_text_field.delegate = self

Và nhớ gọi registerForKeyboardNotificationstrên viewInit và deregisterFromKeyboardNotificationsthoát.

Chỉnh sửa / Cập nhật: Cú pháp Swift 4.2

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWasShown(notification: NSNotification){
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

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

@objc func keyboardWillBeHidden(notification: NSNotification){
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}

3
Bạn phải gọi registerForPalNotutions tại viewDidLoad, vì vậy bạn sẽ thêm một người quan sát vào trung tâm thông báo khi bàn phím xuất hiện hoặc biến mất khỏi màn hình. Khi các thông báo này kích hoạt, các phương thức bàn phímWasShown và bàn phímWillBeHidden sẽ được gọi và sau đó scrollview sẽ di chuyển theo kích thước bàn phím. Bạn có thể tìm thêm thông tin chi tiết về NotificationCenter tại đây: developer.apple.com/l
Library / mac / documentation / Coloa / Reference / /

12
Cảm ơn, đó chính xác là những gì tôi đang tìm kiếm - một giải pháp được đề xuất của apple. Tuy nhiên, trong trường hợp của tôi, tôi đã có chế độ xem cuộn kéo dài ra ngoài khu vực có thể xem được. Mã này sẽ vô hiệu hóa cuộn sau khi bàn phím sẽ ẩn. Tôi đã xóa "self.scrollView.scrollEnables = false" và nó vẫn không cuộn. Điều làm việc cho tôi là "self.scrollView.contentInset = UIEdgeInsetsZero;" dòng duy nhất này trong sự kiện bàn
phímWillHide

5
Mã hoàn hảo. Nhưng tôi cần sử dụng UIKeyboardFrameEndUserInfoKeythay vì UIKeyboardFrameBeginUserInfoKey, vì sau này trả về chiều cao 0. Và thay đổi điểm nhỏ nhất thành đáy không xuất xứ. if let activeField = self.activeField { var point = activeField.frame.origin point.y += activeField.frame.size.height if (!aRect.contains(point)){ self.scrollView.scrollRectToVisible(activeField.frame, animated: true) } }
Victor Choy

3
@MaX: Nó nên hoạt động, nhưng nếu bạn muốn có giải pháp Swift4, bạn có thể kiểm tra ví dụ iOS này từ cuốn sách của Matt Neuburg mà tôi đề xuất cho tất cả các nhà phát triển iOS :)
Nerkyator

1
@MaX Tôi không chắc đây có phải là một thứ nhanh chóng không, nhưng điều dường như đang xảy ra là textField's didBeginEditingphương thức được gọi là SAU keyboardWillShowphương thức được gọi. Kết quả là, activeFieldbiến vẫn là con số không, có nghĩa là không có cuộn tự động xảy ra. Giải pháp của tôi là thực hiện activeField = textFieldcuộc gọi trong shouldBeginEditingphương thức của textField . Điều này giải quyết thứ tự của các cuộc gọi vấn đề.
HirdayGupta

150

Đây là 2 xu của tôi:

Bạn đã thử chưa: https://github.com/hackiftekhar/IQPalManager

Rất dễ cài đặt Swift hoặc Objective-C.

Đây là cách nó hoạt động:

IQPalManager (Swift): - IQPalManagerSwift có sẵn thông qua CocoaPods, để cài đặt nó chỉ cần thêm dòng sau vào Podfile của bạn: (# 236)

pod 'IQKeyboardManagerSwift'

Trong AppDelegate.swift, chỉ cần nhập khung IQPalManagerSwift và bật IQPalManager.

import IQKeyboardManagerSwift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

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

    IQKeyboardManager.sharedManager().enable = true
    // For Swift 4, use this instead
    // IQKeyboardManager.shared.enable = true


    return true
    }
}

Và đó là tất cả. Dễ dàng!


17
Hoàn hảo. Điều này nên được xây dựng theo mặc định. Có vẻ nực cười là không phải.
NathofGod

1
Điều này thực sự vô lý, nó rất dễ thực hiện và chỉ hoạt động, cộng với bạn có một cách dễ dàng để chuyển qua nhiều trường văn bản
Khoury

chuyển sang nhiều trường văn bản sẽ không hoạt động? không có mũi tên hiển thị trên bàn phím để di chuyển giữa các trường văn bản.
Arsal

1
Đây là một giải pháp tuyệt vời, cảm ơn bạn! Tôi đã mất một chút công sức để có được các Cốc Cốc được thiết lập chính xác, vì chúng hoàn toàn mới đối với tôi. Sau khi tôi thiết lập xong, đó là 2 dòng mã để thực hiện điều này và nó hoạt động hoàn hảo ngay lập tức. Cám ơn rất nhiều!
IcyBlueRose

5
Điều này không hoạt động với tôi trong Swift 4.1 IQPalManager. SharedManager (). Enable = true Đã được chuyển sang IQKeyboardManager.shared.enable = true
Rmalmoe

20

Người mà tôi thấy làm việc hoàn hảo với tôi là thế này:

func textFieldDidBeginEditing(textField: UITextField) {
    if textField == email || textField == password {
        animateViewMoving(true, moveValue: 100)
    }
}

func textFieldDidEndEditing(textField: UITextField) {
    if textField == email || textField == password {
        animateViewMoving(false, moveValue: 100)
    }
}

func animateViewMoving (up:Bool, moveValue :CGFloat){
    let movementDuration:NSTimeInterval = 0.3
    let 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()
}

Bạn cũng có thể thay đổi các giá trị chiều cao. Xóa "câu lệnh if" nếu bạn muốn sử dụng nó cho tất cả các trường văn bản.

Bạn thậm chí có thể sử dụng điều này cho tất cả các điều khiển yêu cầu đầu vào của người dùng như TextView.


5
Di chuyển khung UIView trực tiếp không phải là một giải pháp tuyệt vời. Ngoài ra, điều này bao gồm các giá trị được mã hóa dành riêng cho trường hợp sử dụng này. Tôi sẽ khuyến khích mọi người không thực hiện một giải pháp như thế này và thay vào đó hãy làm một cái gì đó gần với thực tiễn tốt nhất như được mô tả trong câu trả lời được chấp nhận.
MobileVet

@MobileVet Đã hiểu, nhưng đây là một trong những hoạt động.
Tarvo Mäesepp

logic riêng biệt tuyệt vời mà không thay đổi mã của chúng tôi
Dilip Jangid

6

Có cách nào để màn hình chỉ di chuyển khi các trường dưới cùng được chỉnh sửa không?

Tôi đã gặp một vấn đề tương tự và tìm thấy một giải pháp khá đơn giản mà không cần sử dụng scrollView, và thay vào đó sử dụng các câu lệnh if trong các phương thức bàn phímWillShow / Hide.

func keyboardWillShow(notification: NSNotification) {
    if bottomText.editing{
        self.view.window?.frame.origin.y = -1 * getKeyboardHeight(notification)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if self.view.window?.frame.origin.y != 0 {
        self.view.window?.frame.origin.y += getKeyboardHeight(notification)
    }
}

Đây là một giải pháp tốt cho tôi vì tôi chỉ có hai trường văn bản.

Chuyển toàn bộ chế độ xem lên: chỉ khi các trường văn bản nhất định (bottomText) được chỉnh sửa

Chuyển toàn bộ chế độ xem xuống: chỉ khi chế độ xem không ở vị trí ban đầu


5

Chỉ cần sử dụng tiện ích mở rộng này để di chuyển bất kỳ UIView nào khi bàn phím được trình bày.

extension UIView {
    func bindToKeyboard(){
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChange(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
    }

    @objc func keyboardWillChange(_ notification: NSNotification){
        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let beginningFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let endFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

        let deltaY = endFrame.origin.y - beginningFrame.origin.y

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.frame.origin.y += deltaY
        }, completion: nil)
    }
}

Sau đó, trong viewdidload của bạn liên kết khung nhìn của bạn với bàn phím

UiView.bindToKeyboard()

Điều này di chuyển chế độ xem lên ngay cả khi không cần thiết và nếu trường văn bản ở trên cùng của chế độ xem, nó sẽ tăng lên và sẽ không hiển thị. Đây không phải là một giải pháp tốt.
Shivam Pokhriyal

4

Tại sao không thực hiện điều này trong một UITableViewControll thay thế? Bàn phím sẽ không ẩn bất kỳ trường văn bản nào khi nó được hiển thị.


Đây thực sự là cách dễ nhất và mạnh mẽ nhất. Và nó hoạt động ngay cả với các điều khiển sử dụng InputView tùy chỉnh thay vì bàn phím mặc định (thông báo UIKeyboard không hoạt động cho những điều này)
Radu Simionescu

1
Có một vấn đề là bạn phải cẩn thận, nếu chế độ xem bảng được nhúng (thay vì là "toàn bộ trang"). Đối với bất kỳ ai vấp phải điều đó, giải pháp được giải thích trong các bài đăng như thế nàythế này . Hy vọng nó sẽ giúp ai đó xử lý "vấn đề hoàn toàn ngu ngốc nhất trong tất cả Apple"!
Fattie

3

Swift 4 (** cập nhật ) với phần mở rộng **

  1. thêm các nút trong một container
  2. kết nối ràng buộc dưới cùng của container với IBOutlet containerBtmConstrain
  3. inViewDidLoad

    self.containerDependOnKeyboardBottomConstrain = containerBtmConstrain
    self.watchForKeyboard() 
  4. thêm phần mở rộng sau

    import UIKit
    
    private var xoAssociationKeyForBottomConstrainInVC: UInt8 = 0
    
    extension UIViewController {
    
        var containerDependOnKeyboardBottomConstrain :NSLayoutConstraint! {
            get {
                return objc_getAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC) as? NSLayoutConstraint
            }
            set(newValue) {
                objc_setAssociatedObject(self, &xoAssociationKeyForBottomConstrainInVC, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
            }
        }
    
        func watchForKeyboard() {
            NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown(notification:)), name:UIResponder.keyboardWillShowNotification, object: nil);
            NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide(notification:)), name:UIResponder.keyboardWillHideNotification, object: nil);
        }
    
        @objc func keyboardWasShown(notification: NSNotification) {
            let info = notification.userInfo!
            guard let keyboardFrame: CGRect = (info[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
              return
            }
    
            UIView.animate(withDuration: 0.3, animations: { () -> Void in
                self.containerDependOnKeyboardBottomConstrain.constant = -keyboardFrame.height
                self.view.layoutIfNeeded()
            })
        }
    
        @objc func keyboardWillHide(notification: NSNotification) {
            UIView.animate(withDuration: 0.3, animations: { () -> Void in
                self.containerDependOnKeyboardBottomConstrain.constant = 0
                self.view.layoutIfNeeded()
            })
        }
    }

1
Cảm ơn, bạn đời. Đó là tất cả về chìa khóa bên phải. Tôi đã sử dụng UIKeyboardFrameBeginUserInfoKey và bây giờ sử dụng UIKeyboardFrameEndUserInfoKey xử lý nó một cách duyên dáng.
Felipe

2

Tôi sử dụng SwiftLint, có một vài vấn đề với định dạng của câu trả lời được chấp nhận. Đặc biệt:

không có khoảng trắng trước dấu hai chấm, không ép buộc, thích UIEdgeInset (top: etc ... thay vì UIEdgeInsetMake.

Vì vậy, đây là những cập nhật cho Swift 3

func registerForKeyboardNotifications() {
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

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

func keyboardWasShown(notification: NSNotification) {
    //Need to calculate keyboard exact size due to Apple suggestions
    scrollView?.isScrollEnabled = true
    var info = notification.userInfo!
    if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
        let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)

        scrollView?.contentInset = contentInsets
        scrollView?.scrollIndicatorInsets = contentInsets

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

func keyboardWillBeHidden(notification: NSNotification) {
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    if let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size {
        let contentInsets: UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize.height, right: 0.0)
        scrollView?.contentInset = contentInsets
        scrollView?.scrollIndicatorInsets = contentInsets
    }

    view.endEditing(true)
    scrollView?.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField) {
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField) {
    activeField = nil
}

1

Tôi nghĩ rằng điều khoản này là sai:

if (!CGRectContainsPoint(aRect, activeField!.frame.origin))

Mặc dù nguồn gốc của activeField có thể nằm phía trên bàn phím, nhưng maxY có thể không ...

Tôi sẽ tạo một điểm 'tối đa' cho activeField và kiểm tra xem đó có phải trong Rect bàn phím không.


0

Đây là phiên bản của tôi sau khi đọc tài liệu do Apple cung cấp và các bài viết trước. Một điều tôi nhận thấy là textView không được xử lý khi được che bởi bàn phím. Thật không may, tài liệu của Apple sẽ không hoạt động vì, vì bất kỳ lý do gì, bàn phím được gọi là SAU văn bảnViewDidBeginEditing được gọi. Tôi đã xử lý điều này bằng cách gọi một phương thức trung tâm để kiểm tra xem bàn phím có được hiển thị VÀ nếu textView hoặc textField đang được chỉnh sửa hay không. Bằng cách này, quá trình chỉ được kích hoạt khi điều kiện CẢ HAI tồn tại.

Một điểm khác với textViews là chiều cao của chúng có thể sao cho bàn phím cắt phần dưới cùng của textView và sẽ không điều chỉnh nếu điểm trên cùng bên trái của chế độ xem. Vì vậy, mã tôi đã viết thực sự lấy điểm dưới cùng bên trái được tham chiếu trên màn hình của bất kỳ textView hoặc textField nào và xem liệu nó có nằm trong tọa độ tham chiếu màn hình của bàn phím được trình bày có nghĩa là bàn phím bao phủ một phần của nó.

let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil)
    if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.origin.x, aRect.maxY))) {
        // scroll textView/textField into view
    }

Nếu bạn đang sử dụng bộ điều khiển điều hướng, lớp con cũng đặt điều chỉnh chế độ xem tự động cho các phần tử thành sai.

self.automaticallyAdjustsScrollViewInsets = false

Nó đi qua từng textView và textField để đặt các đại biểu để xử lý

    for view in self.view.subviews {
        if view is UITextView {
            let tv = view as! UITextView
            tv.delegate = self
        } else if view is UITextField {
            let tf = view as! UITextField
            tf.delegate = self
        }
    }

Chỉ cần đặt lớp cơ sở của bạn thành lớp con được tạo ở đây để có kết quả.

import UIKit

class ScrollingFormViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate {

var activeFieldRect: CGRect?
var keyboardRect: CGRect?
var scrollView: UIScrollView!

override func viewDidLoad() {

    self.automaticallyAdjustsScrollViewInsets = false

    super.viewDidLoad()

    // Do any additional setup after loading the view.
    self.registerForKeyboardNotifications()
    for view in self.view.subviews {
        if view is UITextView {
            let tv = view as! UITextView
            tv.delegate = self
        } else if view is UITextField {
            let tf = view as! UITextField
            tf.delegate = self
        }
    }
    scrollView = UIScrollView(frame: self.view.frame)
    scrollView.scrollEnabled = false
    scrollView.showsVerticalScrollIndicator = false
    scrollView.showsHorizontalScrollIndicator = false
    scrollView.addSubview(self.view)
    self.view = scrollView
}

override func viewDidLayoutSubviews() {
    scrollView.sizeToFit()
    scrollView.contentSize = scrollView.frame.size
    super.viewDidLayoutSubviews()
}

deinit {
    self.deregisterFromKeyboardNotifications()
}

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


func registerForKeyboardNotifications()
{
    //Adding notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWasShown), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ScrollingFormViewController.keyboardWillBeHidden), name: UIKeyboardWillHideNotification, object: nil)
}


func deregisterFromKeyboardNotifications()
{
    //Removing notifies on keyboard appearing
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(notification: NSNotification)
{
    let info : NSDictionary = notification.userInfo!
    keyboardRect = (info[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
    adjustForKeyboard()
}


func keyboardWillBeHidden(notification: NSNotification)
{
    keyboardRect = nil
    adjustForKeyboard()
}

func adjustForKeyboard() {
    if keyboardRect != nil && activeFieldRect != nil {
        let aRect : CGRect = scrollView.convertRect(activeFieldRect!, toView: nil)
        if (CGRectContainsPoint(keyboardRect!, CGPointMake(aRect.origin.x, aRect.maxY)))
        {
            scrollView.scrollEnabled = true
            let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardRect!.size.height, 0.0)
            scrollView.contentInset = contentInsets
            scrollView.scrollIndicatorInsets = contentInsets
            scrollView.scrollRectToVisible(activeFieldRect!, animated: true)
        }
    } else {
        let contentInsets : UIEdgeInsets = UIEdgeInsetsZero
        scrollView.contentInset = contentInsets
        scrollView.scrollIndicatorInsets = contentInsets
        scrollView.scrollEnabled = false
    }
}

func textViewDidBeginEditing(textView: UITextView) {
    activeFieldRect = textView.frame
    adjustForKeyboard()
}

func textViewDidEndEditing(textView: UITextView) {
    activeFieldRect = nil
    adjustForKeyboard()
}

func textFieldDidBeginEditing(textField: UITextField)
{
    activeFieldRect = textField.frame
    adjustForKeyboard()
}

func textFieldDidEndEditing(textField: UITextField)
{
    activeFieldRect = nil
    adjustForKeyboard()
}

}

0

Câu trả lời tuyệt vời đã được đưa ra nhưng đây là một cách khác để giải quyết tình huống này (sử dụng Swift 3x ):

Trước hết hãy gọi phương thức sau trong viewWillAppear()

func registerForKeyboardNotifications() {

NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillBeHidden), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

}

Bây giờ hãy thực hiện một IBOutlettrong UIViewnhững hạn chế hàng đầu của bạn UIViewcontrollernhư thế này: (đây UIViewlà phần phụ của UIScrollViewđiều đó có nghĩa là bạn nên có một UIScrollViewcho tất cả các bạn subViews)

@IBOutlet weak var loginViewTopConstraint: NSLayoutConstraint!

Và một biến khác như sau và thêm một đại biểu, nghĩa là UITextFieldDelegate:

var activeTextField = UITextField() //This is to keep the reference of UITextField currently active

Sau đó là phần ma thuật chỉ cần dán phần này bên dưới đoạn trích :

func keyboardWasShown(_ notification: Notification) {

let keyboardInfo  = notification.userInfo as NSDictionary?

//print(keyboardInfo!)

let keyboardFrameEnd: NSValue? = (keyboardInfo?.value(forKey: UIKeyboardFrameEndUserInfoKey) as? NSValue)

let keyboardFrameEndRect: CGRect? = keyboardFrameEnd?.cgRectValue


if activeTextField.frame.origin.y + activeTextField.frame.size.height + 10 > (keyboardFrameEndRect?.origin.y)! {

    UIView.animate(withDuration: 0.3, delay: 0, options: .transitionFlipFromTop, animations: {() -> Void in

        //code with animation

        //Print some stuff to know what is actually happening
        //print(self.activeTextField.frame.origin.y)
        //print(self.activeTextField.frame.size.height)
        //print(self.activeTextField.frame.size.height)

        self.loginViewTopConstraint.constant = -(self.activeTextField.frame.origin.y + self.activeTextField.frame.size.height - (keyboardFrameEndRect?.origin.y)!) - 30.0

        self.view.layoutIfNeeded()

    }, completion: {(_ finished: Bool) -> Void in
        //code for completion

    })
}
}

func keyboardWillBeHidden(_ notification: Notification) {

UIView.animate(withDuration: 0.3, animations: {() -> Void in

    self.loginViewTopConstraint.constant = self.view.frame.origin.y
    self.view.layoutIfNeeded()

})
}

//MARK: textfield delegates
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    activeTextField = textField
    return true
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

           switch textField {
    case YOUR_TEXTFIELD_ONE:
        YOUR_TEXTFIELD_TWO.becomeFirstResponder()
        break
    case YOUR_TEXTFIELD_TWO:
        YOUR_TEXTFIELD_THREE.becomeFirstResponder()
        break
    default:
        textField.resignFirstResponder()
        break
    }
    return true
}

Bây giờ là đoạn cuối cùng:

//Remove Keyboard Observers
override func viewWillDisappear(_ animated: Bool) {

NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)

NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

Đừng quên để các đại biểu assign cho tất cả các bạn UITextFields trongUIStoryboard

Chúc may mắn!


0

Cú pháp Swift 3:

func textFieldDidBeginEditing(_ textField: UITextField) {
    // add if for some desired textfields
        animateViewMoving(up: true, moveValue: 100)
}

func textFieldDidEndEditing(_ textField: UITextField) {
    // add if for some desired textfields
        animateViewMoving(up: false, moveValue: 100)
}

func animateViewMoving (up:Bool, moveValue :CGFloat){
     textFieldDidEndEditing(_ textField: UITextField) {

    let movementDuration:TimeInterval = 0.5

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

đây là một phương pháp hay để có được những gì bạn muốn, bạn có thể thêm các điều kiện "nếu" cho các trường văn bản nhất định nhưng loại này hoạt động cho tất cả ... Hy vọng nó có thể hữu ích cho mọi người


0

Trước hết, khai báo một biến để xác định UITextField hoạt động của bạn.

Bước 1:-

Như var activeTextField: UITextFieldthế nào?

Bước 2: - Sau đó, thêm hai dòng này trong viewDidLoad.

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)

Bước 3:-

Bây giờ định nghĩa hai phương thức này trong lớp trình điều khiển của bạn.

func keyboardWillShow(_ notification: NSNotification) {

    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

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


func keyboardWillHide(_ notification: NSNotification) {

    let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = true
}


func textFieldDidBeginEditing(_ textField: UITextField){

    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){

    activeField = nil
}

0

cho nhanh chóng 4.2.

Điều này sẽ áp dụng cho bất kỳ hình thức. Không cần scrollview. đừng quên thiết lập đại biểu.

Tạo một var của uitextfield

var clickedTextField = UITextField()

Trong tải viewdid của bạn

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

Biết trường văn bản đã nhấp. có lẽ bạn đang có trường văn bản trên toàn bộ màn hình.

func textFieldDidBeginEditing(_ textField: UITextField) {
    clickedTextField = textField
}

Kiểm tra xem bàn phím có bao phủ trường văn bản hay không.

@objc func keyboardWillShow(sender: NSNotification,_ textField : UITextField) {
    if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {

        if clickedTextField.frame.origin.y > keyboardSize.origin.y {
            self.view.frame.origin.y = keyboardSize.origin.y - clickedTextField.center.y - 20
        }
    }
}

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

Quay lại đóng bàn phím

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

CẬP NHẬT: NSNotification.Name.UIKeyboardWillShow & NSNotification.Name.UIKeyboardWillHide được đổi tên thành UIResponder.keyboardWillShowNotification & UIResponder.keyboardWillHideNotification.


0

Swift : Bạn có thể làm điều này bằng cách kiểm tra textField nào đang được trình bày.

@objc func keyboardWillShow(notification: NSNotification) {
    if self.textField.isFirstResponder == true {
        self.view.frame.origin.y -= 150
     }
}

@objc func keyboardWillHide(notification: NSNotification){
    if self.textField.isFirstResponder == true {
       self.view.frame.origin.y += 150
    }
}

-1

Mã này di chuyển lên trường văn bản bạn đang chỉnh sửa để bạn có thể xem nó trong Swift 3 cho câu trả lời này, bạn cũng phải biến chế độ xem của mình thành UITextFieldDelegate:

var moveValue: CGFloat!
var moved: Bool = false
var activeTextField = UITextField()

func textFieldDidBeginEditing(_ textField: UITextField) {
    self.activeTextField = textField
}
func textFieldDidEndEditing(_ textField: UITextField) {
    if moved == true{
    self.animateViewMoving(up: false, moveValue: moveValue )
        moved = false
    }
}
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()
}

Và sau đó trong viewDidLoad:

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

Cuộc gọi nào (bên ngoài viewDidLoad):

func keyboardWillShow(notification: Notification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        let keyboardHeight = keyboardSize.height
        if (view.frame.size.height-self.activeTextField.frame.origin.y) - self.activeTextField.frame.size.height < keyboardHeight{
            moveValue = keyboardHeight - ((view.frame.size.height-self.activeTextField.frame.origin.y) - self.activeTextField.frame.size.height)
            self.animateViewMoving(up: true, moveValue: moveValue )
            moved = true
        }
    }
}

-1

Swift 3

@IBOutlet var scrollView: UIScrollView!
@IBOutlet var edtEmail: UITextField!
@IBOutlet var bottomTextfieldConstrain: NSLayoutConstraint! // <- this guy is the constrain that connect the bottom of textField to lower object or bottom of page!

 @IBAction func edtEmailEditingDidBegin(_ sender: Any) { 
        self.bottomTextfieldConstrain.constant = 200
        let point = CGPoint(x: 0, y: 200)
        scrollView.contentOffset = point
    }

@IBAction func edtEmailEditingDidEnd(_ sender: Any) { 
    self.bottomTextfieldConstrain.constant = 50
}

-1

Anwser được chấp nhận là gần như hoàn hảo. Nhưng tôi cần sử dụng UIKeyboardFrameEndUserInfoKeythay UIKeyboardFrameBeginUserInfoKey,vì bởi vì keyborad trả về chiều cao 0. Và thay đổi điểm nhỏ nhất thành đáy không xuất xứ.

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

-1

Swift 4 Cập nhật giải pháp của tôi

với hình ảnh động hạn chế trên chương trình bàn phím / ẩn, thưởng thức.

import Foundation
import UIKit

class PhoneController: UIViewController, UITextFieldDelegate{

    var phoneLayoutYConstraint: NSLayoutConstraint?

    override func viewDidLoad() {

        super.viewDidLoad()

        view.backgroundColor = .white

        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyBoardNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        phoneField.delegate = self

        view.addSubview(phoneField)

        NSLayoutConstraint.activate([phoneField.heightAnchor.constraint(equalToConstant: 50),
                                     phoneField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
                                     phoneField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
                                     phoneField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20)])

        phoneLayoutYConstraint = NSLayoutConstraint(item: phoneField, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
        phoneLayoutYConstraint?.isActive = true

    }

    let phoneField: UITextField = {
        let text = UITextField()
        text.translatesAutoresizingMaskIntoConstraints = false
        text.keyboardType = .numberPad
        text.font = UIFont.systemFont(ofSize: 30)
        text.layer.cornerRadius = 5.0
        text.layer.masksToBounds = true
        text.layer.borderColor = UIColor.darkGray.cgColor
        text.layer.borderWidth = 2.0

        return text
    }()


    override func viewDidDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self)
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {

    }


    func textFieldDidEndEditing(_ textField: UITextField) {

    }

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


   @objc func handleKeyBoardNotification(_ notification: NSNotification) {

        if let info = notification.userInfo {

            let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
            let isKeyBoardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow

            var aRect : CGRect = self.phoneField.frame
            aRect.size.height -= keyboardSize!.height


            phoneLayoutYConstraint?.constant = isKeyBoardShowing ? -keyboardSize!.height : 0

            UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
                self.view.layoutIfNeeded()
            }, completion: { (boo) in

            })

        }
    }

}

-1

Swift 4

Bạn có thể dễ dàng di chuyển lên và xuống UITextFieldbằng bàn phím có hình động

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

import UIKit

class ViewController: UIViewController {

    @IBOutlet var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        textField.resignFirstResponder()
    }

    @objc func keyboardWillChange(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.origin.y - curFrame.origin.y

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.textField.frame.origin.y+=deltaY

        },completion: nil)
    }

Lại một giải pháp sẽ đẩy tầm nhìn lên một cách không cần thiết ngay cả khi không cần thiết. Vui lòng cải thiện câu trả lời của bạn là sai lệch
Shivam Pokhriyal

-1

Swift 4.2

Giải pháp của tôi sẽ (theo chiều dọc) tập trung vào chế độ xem UITextFieldnếu vị trí của nó nằm dưới bàn phím.

Bước 1: Tạo tập tin swift mới và UIViewWithKeyboardlớp sao chép-dán .
Bước 2: Trong Trình tạo giao diện, đặt nó làm Lớp tùy chỉnh cho hầu hết các mục hàng đầu của bạn UIView.

import UIKit

class UIViewWithKeyboard: UIView {
    @IBInspectable var offsetMultiplier: CGFloat = 0.75
    private var keyboardHeight = 0 as CGFloat
    private weak var activeTextField: UITextField?
    override func awakeFromNib() {
        super.awakeFromNib()
        NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.textDidBeginEditing),
                                               name: UITextField.textDidBeginEditingNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillShow),
                                               name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(UIViewWithKeyboard.keyboardWillHide),
                                               name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    @objc func textDidBeginEditing(_ notification: NSNotification) {
        self.activeTextField = notification.object as? UITextField
    }

    @objc func keyboardWillShow(_ notification: Notification) {
        if let frameValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
            keyboardHeight = frameValue.cgRectValue.size.height
            if let textField = self.activeTextField {
                let offset = textField.frame.maxY < frame.maxY - keyboardHeight ? 0
                           : textField.frame.maxY - (frame.maxY - keyboardHeight) * offsetMultiplier
                self.setView(offset: offset)
            }
        }
    }

    @objc func keyboardWillHide(_ notification: NSNotification) {
        self.setView(offset: 0)
    }

    func setView(offset: CGFloat) {
        UIView.animate(withDuration: 0.25) {
            self.bounds.origin.y = offset
        }
    }
}

-1

Viết lại cho swift 4.2

Trong ViewDidLoad ..

 NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWasShown), name: UIResponder.keyboardWillShowNotification, object: nil)
 NotificationCenter.default.addObserver(self, selector: #selector(trailViewController.keyboardWillBeHidden), name: UIResponder.keyboardWillHideNotification, object: nil)

Các chức năng còn lại

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWasShown(notification: NSNotification){
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize!.height, right: 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

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

@objc func keyboardWillBeHidden(notification: NSNotification){
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    let keyboardSize = (info[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: -keyboardSize!.height, right: 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = false
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}

-2

"Tôi quên đề cập rằng tôi là người mới sử dụng Swift :( Cú pháp chính xác để kiểm tra điều này là gì? (Làm cách nào để tôi có được tên trường trong hàm này?)"

Đồng ý . Đầu tiên xác nhận với giao thức UITextFieldDelegate

class YourClass:UITextFieldDelegate

Sau đó thực hiện chức năng

func textFieldDidBeginEditing(textField: UITextField!) {

    if textField == txtOne
    {
        println("TextOne")
    }
    if textField == txtTwo
    {
        println("TextTwo")
    }
}

Bạn nên lưu ý rằng cách tiếp cận phù hợp là sử dụng chế độ xem cuộn và đặt chế độ xem nên được chuyển lên / xuống bên trong chế độ xem cuộn và xử lý các sự kiện bàn phím tương ứng


-3

Dành cho Swift 4.2

Mã này sẽ cho phép bạn điều khiển thời điểm trục Y của khung cho kích thước màn hình thiết bị cụ thể.

PS: Mã này sẽ không di chuyển khung một cách thông minh dựa trên vị trí của TextField.

Tạo tiện ích mở rộng cho UIDevice

extension UIDevice {
    enum ScreenType: String {
        case iPhone4_4S = "iPhone 4 or iPhone 4s"
        case iPhones_5_5s_5c_SE = "iPhone 5, iPhone 5s, iPhone 5c or iPhone SE"
        case iPhones_6_6s_7_8 = "iPhone 6, iPhone 6s, iPhone 7 or iPhone 8"
        case iPhones_6Plus_6sPlus_7Plus_8Plus = "iPhone 6 Plus, iPhone 6s Plus, iPhone 7 Plus or iPhone 8 Plus"
        case iPhoneX_Xs = "iPhone X, iPhone Xs"
        case iPhoneXR = "iPhone XR"
        case iPhoneXSMax = "iPhone Xs Max"
        case unknown
    }
    var screenType: ScreenType {
        switch UIScreen.main.nativeBounds.height {
        case 960:
            return .iPhone4_4S
        case 1136:
            return .iPhones_5_5s_5c_SE
        case 1334:
            return .iPhones_6_6s_7_8
        case 1920, 2208:
            return .iPhones_6Plus_6sPlus_7Plus_8Plus
        case 1792:
            return .iPhoneXR
        case 2436:
            return .iPhoneX_Xs
        case 2688:
            return .iPhoneXSMax
        default:
            return .unknown
        }
    }
}

Thêm NotificationObserver trên 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)

Bộ chọn

@objc func keyboardWillShow(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        if self.view.frame.origin.y == 0 {
            switch (UIDevice.current.screenType.rawValue) {
            case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue):
                self.view.frame.origin.y -= 210
            case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue):
                self.view.frame.origin.y -= 110
            case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue):
                self.view.frame.origin.y -= 80
            case (UIDevice.ScreenType.iPhoneX_Xs.rawValue):
                self.view.frame.origin.y -= 70
            case (UIDevice.ScreenType.iPhoneXR.rawValue):
                self.view.frame.origin.y -= 70
            case (UIDevice.ScreenType.iPhoneXSMax.rawValue):
                self.view.frame.origin.y -= 70
            default:
                self.view.frame.origin.y -= 150
            }
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        if self.view.frame.origin.y != 0 {
            switch (UIDevice.current.screenType.rawValue) {
            case (UIDevice.ScreenType.iPhones_5_5s_5c_SE.rawValue):
                self.view.frame.origin.y += 210
            case (UIDevice.ScreenType.iPhones_6_6s_7_8.rawValue):
                self.view.frame.origin.y += 110
            case (UIDevice.ScreenType.iPhones_6Plus_6sPlus_7Plus_8Plus.rawValue):
                self.view.frame.origin.y += 80
            case (UIDevice.ScreenType.iPhoneX_Xs.rawValue):
                self.view.frame.origin.y += 70
            case (UIDevice.ScreenType.iPhoneXR.rawValue):
                self.view.frame.origin.y += 70
            case (UIDevice.ScreenType.iPhoneXSMax.rawValue):
                self.view.frame.origin.y += 70
            default:
                self.view.frame.origin.y += 150
            }
        }
    }
}

1
Nói chung, tôi sẽ nói rằng đó là một cách tiếp cận tồi và khá tốn kém để sử dụng các loại cụ thể của thiết bị và các kích thước liên quan đến bố cục mã cứng khi chúng liên tục thay đổi.
Johan
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.