[ios] 키보드가 입력 필드를 덮을 때만 뷰를 위로 이동

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
}



답변

이 문서 에서 문제는 Apple 에서 잘 설명 합니다. 이 페이지의 예제 코드 ( Listing 4-1)는 필요한 것을 정확하게 수행하며 현재 편집이 키보드 아래에 있어야하는 경우에만보기를 스크롤합니다. 필요한 컨트롤 만 scrollViiew에 넣으면됩니다. 유일한 문제는 이것이 Objective-C이며 Swift..so에서 필요하다고 생각합니다.

변수 선언

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

그리고 registerForKeyboardNotificationsviewInit 및 deregisterFromKeyboardNotificationsexit 를 호출해야 합니다 .

편집 / 업데이트 : 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
}


답변

여기 내 2 센트가 있습니다 :

https://github.com/hackiftekhar/IQKeyboardManager 를 사용해 보셨습니까?

Swift 또는 Objective-C를 매우 쉽게 설치할 수 있습니다.

작동 방식은 다음과 같습니다.

IQKeyboardManager (Swift) :-CocoaPods를 통해 IQKeyboardManagerSwift를 사용할 수 있습니다. 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
    }
}

그리고 그게 다야. 쉬운!


답변

내가 완벽하게 작동하는 것으로 밝혀진 것은 다음과 같습니다.

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 문”을 제거하십시오.

TextView와 같은 사용자 입력이 필요한 모든 컨트롤에이 기능을 사용할 수도 있습니다.


답변

하단 필드 를 편집 할 때만 화면을 이동 시키는 방법 이 있습니까?

비슷한 문제가 있었고 scrollView 사용 하지 않고 keyboardWillShow / Hide 메서드 내 if 문을 사용 하지 않고 매우 간단한 해결책 찾았습니다 .

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)가 편집 된 경우에만

전체보기를 아래로 이동 : 보기가 원래 위치에 있지 않은 경우에만


답변

키보드가 표시 될 때이 확장을 사용하여 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)
    }
}

그런 다음 viewdidload에서 뷰를 키보드에 바인딩하십시오.

UiView.bindToKeyboard()


답변

대신 UITableViewController에서 이것을 구현하지 않는 이유는 무엇입니까? 키보드는 표시 될 때 텍스트 필드를 숨기지 않습니다.


답변

확장명이 포함 된 스위프트 4 (** 업데이트 됨 ) **

  1. 하나의 컨테이너에 버튼을 추가
  2. 컨테이너의 하단 제약 조건을 IBOutlet 컨테이너와 연결하십시오.
  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()
            })
        }
    }