เลื่อนมุมมองขึ้นเมื่อแป้นพิมพ์ครอบคลุมช่องสัญญาณเข้าเท่านั้น


148

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

มีวิธีให้หน้าจอเคลื่อนที่เฉพาะเมื่อแก้ไขฟิลด์ด้านล่างหรือไม่

ฉันใช้รหัสนี้ฉันพบที่นี่ :

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
}

อาจเป็นไปได้ที่คุณสามารถใช้ func textFieldDidBeginEditing (textField: UITextField!) {} เพื่อตรวจสอบว่า textfield ได้เริ่มแก้ไขและทำการซ่อน / แสดงแป้นพิมพ์
humblePilgrim

ฉันลืมที่จะพูดถึงว่าฉันใหม่กับ Swift :( ไวยากรณ์ที่ถูกต้องในการตรวจสอบนี้จะเป็นอย่างไร (ฉันจะรับชื่อฟิลด์ในฟังก์ชั่นนี้ได้อย่างไร)
John Allijn

คำตอบ:


211

ปัญหาของคุณคือการอธิบายอย่างดีในเอกสารนี้โดยแอปเปิ้ล โค้ดตัวอย่างในหน้านี้ (at Listing 4-1) ทำสิ่งที่คุณต้องการอย่างแน่นอนมันจะเลื่อนมุมมองของคุณเฉพาะเมื่อการแก้ไขปัจจุบันควรอยู่ภายใต้แป้นพิมพ์ คุณจะต้องใส่ส่วนควบคุมที่คุณต้องการใน scrollViiew ปัญหาเดียวคือนี่คือ Objective-C และฉันคิดว่าคุณต้องการใน Swift .. ดังนั้น .. มันอยู่ที่:

ประกาศตัวแปร

var activeField: UITextField?

จากนั้นเพิ่มวิธีการเหล่านี้

 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
}

ให้แน่ใจว่าได้ประกาศ ViewController ของคุณเป็นUITextFieldDelegateและตั้งผู้รับมอบสิทธิ์ที่ถูกต้องในวิธีการเริ่มต้นของคุณ: ex:

self.you_text_field.delegate = self

และอย่าลืมโทรไปregisterForKeyboardNotificationsที่ viewInit และderegisterFromKeyboardNotificationsเมื่อออกจาก

แก้ไข / อัปเดต: Swift 4.2 Syntax

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
คุณต้องโทรไปที่ registerForKeyboardNotifications ที่ viewDidLoad ดังนั้นคุณจะเพิ่มผู้สังเกตการณ์ในศูนย์การแจ้งเตือนเมื่อแป้นพิมพ์ปรากฏขึ้นหรือหายไปจากหน้าจอ เมื่อการแจ้งเตือนเหล่านี้เริ่มต้นขึ้นเมธอด keyboardWasShown และ keyboardWillBeHidden จะถูกเรียกใช้และจากนั้น scrollview จะเลื่อนตามขนาดคีย์บอร์ด คุณสามารถหาข้อมูลรายละเอียดเพิ่มเติมเกี่ยวกับ NotificationCenter ได้ที่นี่: developer.apple.com/library/mac/documentation/Cocoa/Reference/…
Nerkyator

12
ขอบคุณนั่นคือสิ่งที่ฉันกำลังมองหา - โซลูชั่นที่แนะนำสำหรับแอปเปิ้ล อย่างไรก็ตามในกรณีของฉันฉันมีมุมมองเลื่อนที่ขยายออกนอกพื้นที่ที่สามารถดูได้ รหัสนี้จะปิดการใช้งานการเลื่อนหลังจากแป้นพิมพ์จะซ่อน ฉันลบ "self.scrollView.scrollEnabled = false" และจะยังไม่เลื่อน สิ่งที่ใช้ได้ผลสำหรับฉันคือ "self.scrollView.contentInset = UIEdgeInsetsZero;" บรรทัดเดียวในแป้นพิมพ์เหตุการณ์
WillHide

5
รหัสที่สมบูรณ์แบบ แต่ฉันต้องใช้UIKeyboardFrameEndUserInfoKeyแทน UIKeyboardFrameBeginUserInfoKeyเพราะหลังสูงกลับ 0 และเปลี่ยนจุด hittest ที่ด้านล่างไม่ได้กำเนิด 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: มันควรจะทำงาน แต่ถ้าคุณต้องการแก้ไข Swift4 คุณสามารถตรวจสอบ นี้ตัวอย่างเช่น iOS ของคุณจากแมตต์ Neuburgหนังสือของที่ฉันขอแนะนำให้นักพัฒนา iOS ของคุณทั้งหมด :)
Nerkyator

1
@ MaX ฉันไม่แน่ใจว่าสิ่งนี้เป็นสิ่งที่รวดเร็วโดยเฉพาะ แต่สิ่งที่ดูเหมือนจะเกิดขึ้นคือtextField's didBeginEditingวิธีการที่เรียกว่าหลังจากkeyboardWillShowวิธีที่เรียกว่า เป็นผลให้activeFieldตัวแปรยังคงเป็นศูนย์ซึ่งหมายความว่าไม่มีการเลื่อนอัตโนมัติเกิดขึ้น ทางออกของฉันคือการactiveField = textFieldโทรในshouldBeginEditingวิธีการของ textField วิธีนี้จะช่วยแก้ไขปัญหาการโทรออก
HirdayGupta

150

นี่คือ 2 เซ็นต์ของฉัน:

คุณได้ลองแล้ว: https://github.com/hackiftekhar/IQKeyboardManager

ง่ายมากที่จะติดตั้ง Swift หรือ Objective-C

นี่คือวิธีการ:

IQKeyboardManager (Swift): - IQKeyboardManagerSwift มีให้บริการผ่าน CocoaPods เพื่อติดตั้งเพียงเพิ่มบรรทัดต่อไปนี้ใน Podfile ของคุณ: (# 236)

pod 'IQKeyboardManagerSwift'

ใน AppDelegate.swift เพียงนำเข้ากรอบ IQKeyboardManagerSwift และเปิดใช้งาน IQKeyboardManager

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

และนั่นคือทั้งหมดที่ ง่าย!


17
สมบูรณ์ โดยค่าเริ่มต้นนี้ควรสร้างขึ้น ดูเหมือนไร้สาระที่มันไม่ได้
NathofGod

1
นี่มันไร้สาระจริง ๆ มันใช้งานง่ายและใช้งานได้ง่ายรวมถึงคุณจะได้วิธีง่ายๆในการสลับไปมาในช่องข้อความต่างๆ
Khoury

การสลับเป็นฟิลด์ข้อความหลายรายการจะไม่ทำงานใช่ไหม ไม่มีลูกศรแสดงบนแป้นพิมพ์เพื่อเลื่อนไปมาระหว่างฟิลด์ข้อความ
Arsal

1
นี่เป็นทางออกที่น่าอัศจรรย์ขอบคุณ! ฉันต้องทำงานเล็กน้อยเพื่อให้ CocoaPods ติดตั้งอย่างถูกต้องเนื่องจากเป็นสิ่งใหม่สำหรับฉัน หลังจากที่ฉันตั้งค่านั้นมันเป็นรหัส 2 บรรทัดที่จะใช้สิ่งนี้และมันทำงานได้อย่างสมบูรณ์แบบทันทีจากค้างคาว ขอบคุณมาก!
IcyBlueRose

5
นี้ไม่ได้ผลสำหรับผมในสวิฟท์ 4.1 IQKeyboardManager.sharedManager () เปิดใช้งาน = true. จึงได้มีการเปลี่ยนไป IQKeyboardManager.shared.enable = true
Rmalmoe

20

สิ่งที่ฉันพบว่าทำงานได้อย่างสมบูรณ์แบบสำหรับฉันคือ:

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

คุณสามารถเปลี่ยนค่าความสูงได้ ลบ "if statement" หากคุณต้องการใช้กับทุก text field

คุณสามารถใช้สิ่งนี้สำหรับการควบคุมทั้งหมดที่ต้องการให้ผู้ใช้ป้อนข้อมูลเช่น TextView


5
การย้ายเฟรม UIView โดยตรงไม่ใช่วิธีที่ยอดเยี่ยม นอกจากนี้ยังรวมถึงค่าฮาร์ดโค้ดที่เฉพาะกับกรณีการใช้งานนี้ ฉันขอแนะนำให้ผู้คนไม่ใช้วิธีแก้ปัญหาเช่นนี้และทำสิ่งที่ใกล้เคียงกับแนวทางปฏิบัติที่ดีที่สุดตามที่อธิบายไว้ในคำตอบที่ยอมรับ
MobileVet

@ MobileVet เข้าใจ แต่นี่เป็นสิ่งที่ใช้ได้
Tarvo Mäesepp

ตรรกะแยกที่น่าตื่นตาตื่นใจโดยไม่ต้องเปลี่ยนรหัสของเรา
Dilip Jangid

6

มีวิธีให้หน้าจอเคลื่อนที่เฉพาะเมื่อแก้ไขฟิลด์ด้านล่างหรือไม่

ฉันมีปัญหาที่คล้ายกันและพบวิธีแก้ปัญหาที่ค่อนข้างตรงไปตรงมาโดยไม่ต้องใช้ scrollView และแทนที่จะใช้คำสั่ง if ภายใน keyboardWillShow / 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)
    }
}

นี่เป็นทางออกที่ดีสำหรับฉันเพราะฉันมีเพียงสองช่องข้อความ

เลื่อนมุมมองทั้งขึ้น:เฉพาะเมื่อมีการแก้ไขฟิลด์ข้อความ (bottomText)

เลื่อนมุมมองทั้งหมดลง:เฉพาะเมื่อมุมมองไม่ได้อยู่ในตำแหน่งดั้งเดิม


5

เพียงใช้ส่วนขยายนี้เพื่อย้าย UIView ใด ๆ เมื่อมีการนำเสนอแป้นพิมพ์

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

จากนั้นในมุมมองของคุณโหลดผูกมุมมองของคุณกับแป้นพิมพ์

UiView.bindToKeyboard()

สิ่งนี้จะย้ายมุมมองขึ้นแม้ว่าจะไม่จำเป็นและถ้าฟิลด์ข้อความอยู่ด้านบนของมุมมองก็จะขึ้นไปและจะมองไม่เห็น นี่ไม่ใช่ทางออกที่ดี
Shivam Pokhriyal

4

ทำไมไม่ใช้สิ่งนี้ใน UITableViewController แทน? แป้นพิมพ์จะไม่ซ่อนฟิลด์ข้อความใด ๆ เมื่อแสดง


นี่เป็นวิธีที่ง่ายที่สุดและแข็งแกร่งที่สุด และใช้งานได้กับตัวควบคุมที่ใช้ InputView แบบกำหนดเองแทนแป้นพิมพ์เริ่มต้น (การแจ้งเตือน UIKeyboard ไม่ทำงานสำหรับสิ่งเหล่านี้)
Radu Simionescu

1
มีปัญหาที่คุณต้องระวังหากมุมมองตารางฝังอยู่ (แทนที่จะเป็น "ทั้งหน้า") สำหรับทุกคนที่สะดุดขึ้นมาว่าการแก้ปัญหาจะอธิบายในการโพสต์เช่นนี้และนี้ หวังว่ามันจะช่วยให้ใครบางคนจัดการกับ "ปัญหาที่โง่ที่สุดใน Apple"!
Fattie

3

Swift 4 (อัพเดทล่าสุด ) พร้อมส่วนขยาย **

  1. เพิ่มปุ่มในที่เดียว
  2. เชื่อมต่อข้อ จำกัด ด้านล่างของภาชนะด้วย IBOutlet containerBtmConstrain
  3. inViewDidLoad

    self.containerDependOnKeyboardBottomConstrain = containerBtmConstrain
    self.watchForKeyboard() 
  4. เพิ่มนามสกุลต่อไปนี้

    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
ขอบคุณเพื่อน มันคือทั้งหมดที่เกี่ยวกับกุญแจที่ถูกต้อง ฉันใช้ UIKeyboardFrameBeginUserInfoKey และตอนนี้ใช้ UIKeyboardFrameEndUserInfoKey จัดการมันอย่างสง่างาม
เฟลิเป้

2

ฉันใช้ SwiftLint ซึ่งมีปัญหาเล็กน้อยกับการจัดรูปแบบของคำตอบที่ยอมรับ โดยเฉพาะ:

ไม่มีที่ว่างก่อนที่โคลอนไม่ต้องใช้กำลังในการคัดเลือกให้เลือก UIEdgeInset (ด้านบน: ฯลฯ ... แทนที่จะเป็น UIEdgeInsetMake

ดังนั้นนี่คือการอัปเดตเหล่านั้นสำหรับ 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

ฉันคิดว่าประโยคนี้ผิด

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

ในขณะที่ต้นกำเนิดของ activeField อาจอยู่เหนือคีย์บอร์ด แต่ maxY อาจไม่ ...

ฉันจะสร้างจุด 'max' สำหรับ activeField และตรวจสอบว่าอยู่ในแป้นพิมพ์ Rect หรือไม่


0

นี่คือรุ่นของฉันหลังจากอ่านเอกสารที่จัดทำโดย Apple และโพสต์ก่อนหน้า สิ่งหนึ่งที่ฉันสังเกตเห็นคือ textView ไม่ได้รับการจัดการเมื่อครอบคลุมโดยแป้นพิมพ์ น่าเสียดายที่เอกสารของ Apple ไม่สามารถใช้งานได้เพราะไม่ว่าด้วยเหตุผลใดก็ตามแป้นพิมพ์นั้นเรียกว่าหลังจากข้อความ textViewDidBeginEditing ถูกเรียก ฉันจัดการสิ่งนี้ด้วยการเรียกวิธีการส่วนกลางที่ตรวจสอบว่าแป้นพิมพ์แสดงขึ้นมาหรือไม่และหากมีการแก้ไข textView หรือ textField ด้วยวิธีนี้กระบวนการจะทำงานเมื่อมีเงื่อนไข BOTH เท่านั้น

อีกจุดหนึ่งที่มี textViews ก็คือความสูงของมันอาจเป็นไปได้ที่คีย์บอร์ดจะหนีบที่ด้านล่างของ textView และจะไม่ปรับถ้าจุดบนซ้ายของมุมมองอยู่ ดังนั้นรหัสที่ฉันเขียนจะใช้จุดล่างซ้ายของหน้าจออ้างอิง textView หรือ textField ใด ๆ และดูว่ามันอยู่ในพิกัดอ้างอิงหน้าจอของแป้นพิมพ์ที่นำเสนอหมายความว่าแป้นพิมพ์ครอบคลุมบางส่วนของมัน

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

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

self.automaticallyAdjustsScrollViewInsets = false

มันเดินผ่านแต่ละ textView และ textField เพื่อกำหนดผู้ได้รับมอบหมายสำหรับการจัดการ

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

เพียงตั้งคลาสฐานของคุณเป็นคลาสย่อยที่สร้างขึ้นที่นี่เพื่อรับผลลัพธ์

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

มีคำตอบที่ยอดเยี่ยมอยู่แล้ว แต่นี่เป็นวิธีที่แตกต่างในการจัดการกับสถานการณ์นี้ (ใช้Swift 3x ):

ก่อนอื่นให้เรียกวิธีการต่อไปนี้ใน 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)

}

ตอนนี้ใช้เวลาหนึ่งIBOutletของUIView's ข้อ จำกัด ด้านบนของคุณUIViewcontrollerเช่นนี้(ที่นี่UIViewเป็น subview ของUIScrollViewหมายความว่าคุณควรจะมีUIScrollViewทั้งหมดของคุณsubViews)

@IBOutlet weak var loginViewTopConstraint: NSLayoutConstraint!

และตัวแปรอื่นเช่นการติดตามและเพิ่มผู้ได้รับมอบหมายเช่นUITextFieldDelegate:

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

หลังจากนั้นที่นี่คือส่วนเวทย์มนตร์เพียงแค่วางด้านล่าง ตัวอย่าง :

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
}

ตอนนี้เป็นข้อมูลโค้ดสุดท้าย:

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

อย่าลืมที่จะได้รับมอบหมายกำหนดที่จะของคุณทั้งหมดUITextFieldในUIStoryboard

โชคดี!


0

ไวยากรณ์ของ 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()
}

นี่เป็นวิธีการที่ดีในการได้รับสิ่งที่คุณต้องการคุณสามารถเพิ่มเงื่อนไข "if" สำหรับ textfields บางชนิด แต่ประเภทนี้ใช้ได้กับทุกคน ... หวังว่ามันจะมีประโยชน์สำหรับทุกคน


0

ก่อนอื่นให้ประกาศตัวแปรเพื่อระบุ UITextField ที่ใช้งานอยู่ของคุณ

ขั้นตอนที่ 1:-

ชอบvar activeTextField: UITextFieldไหม

ขั้นตอนที่ 2: - หลังจากนี้ให้เพิ่มสองบรรทัดนี้ใน 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)

ขั้นตอนที่ 3: -

ตอนนี้กำหนดวิธีการทั้งสองนี้ในระดับควบคุมของคุณ

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

สำหรับรวดเร็ว 4.2

สิ่งนี้จะใช้กับทุกรูปแบบ ไม่จำเป็นต้องใช้ scrollview อย่าลืมตั้งผู้แทน

ทำให้เป็น uitextfield ที่หลากหลาย

var clickedTextField = UITextField()

ในมุมมองโหลดของคุณ

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

รู้ฟิลด์ข้อความที่ถูกคลิก บางทีคุณอาจมี textfields อยู่เต็มหน้าจอ

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

ตรวจสอบว่าแป้นพิมพ์ครอบคลุมฟิลด์ข้อความหรือไม่

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

กลับไปที่แป้นพิมพ์ปิด

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

อัปเดต: NSNotification.Name.UIKeyboardWillShow & NSNotification.Name.UIKeyboardWillHide จะถูกเปลี่ยนชื่อเป็น UIResponder.keyboardWillShowNotification & UIResponder.keyboardWillHideNotification ตามลำดับ


0

Swift : คุณสามารถทำได้โดยการตรวจสอบ textField ที่จะถูกนำเสนอ

@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

รหัสนี้เลื่อนขึ้นช่องข้อความที่คุณกำลังแก้ไขเพื่อให้คุณสามารถดูได้ใน Swift 3 สำหรับคำตอบนี้คุณต้องทำให้มุมมองของคุณเป็น 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()
}

จากนั้นใน viewDidLoad:

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

สายไหน (นอก 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

สวิฟท์ 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 ที่ยอมรับนั้นเกือบจะสมบูรณ์แบบ แต่ฉันต้องใช้UIKeyboardFrameEndUserInfoKeyแทนUIKeyboardFrameBeginUserInfoKey,เพราะความสูงกลับมาที่คีย์บอร์ความสูง 0 และเปลี่ยนจุด hittest ที่ด้านล่างไม่ใช่ต้นกำเนิด

    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 อัปเดตโซลูชันของฉัน

ด้วยภาพเคลื่อนไหวที่ จำกัด ในการแสดง / ซ่อนแป้นพิมพ์เพลิดเพลิน

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

สวิฟต์ 4

คุณสามารถเลื่อนขึ้นและลงได้อย่างง่ายดายUITextFieldด้วยแป้นพิมพ์พร้อมแอนิเมชัน

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

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

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

-1

สวิฟต์ 4.2

โซลูชันของฉันจะจัดมุมมองให้อยู่กึ่งกลาง UITextFieldหากตำแหน่งอยู่ใต้แป้นพิมพ์

ขั้นตอนที่ 1: สร้างไฟล์ swift และUIViewWithKeyboardคลาสcopy-paste ใหม่
ขั้นตอนที่ 2: ใน Interface Builder 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

เขียนใหม่สำหรับรวดเร็ว 4.2

ใน 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)

เหลือ Funtions

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

"ฉันลืมที่จะพูดถึงว่าฉันใหม่กับ Swift :( ไวยากรณ์ที่ถูกต้องในการตรวจสอบนี้จะเป็นอย่างไร (ฉันจะรับชื่อฟิลด์ในฟังก์ชันนี้ได้อย่างไร)"

ตกลง . ขั้นแรกให้ยืนยันโปรโตคอล UITextFieldDelegate

class YourClass:UITextFieldDelegate

จากนั้นใช้ฟังก์ชัน

func textFieldDidBeginEditing(textField: UITextField!) {

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

คุณควรทราบว่าวิธีการที่เหมาะสมคือการใช้ scrollview และวางมุมมองที่ควรเลื่อนขึ้น / ลงภายในมุมมองเลื่อนและจัดการเหตุการณ์แป้นพิมพ์ตามลำดับ


-3

สำหรับ Swift 4.2

รหัสนี้จะช่วยให้คุณสามารถควบคุมช่วงเวลาแกน Y ของเฟรมสำหรับขนาดหน้าจอของอุปกรณ์ที่ระบุ

PS: รหัสนี้จะไม่ย้ายเฟรมอย่างชาญฉลาดตามตำแหน่งของ TextField

สร้างส่วนขยายสำหรับ 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
        }
    }
}

เพิ่ม NotificationObserver บน 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 ((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
โดยทั่วไปแล้วฉันจะบอกว่ามันเป็นวิธีการที่ไม่ดีและค่อนข้างแพงในการใช้อุปกรณ์เฉพาะและมิติข้อมูลที่เกี่ยวข้องกับเค้าโครงฮาร์ดโค้ดเนื่องจากมีการเปลี่ยนแปลงอยู่ตลอดเวลา
Johan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.