수색…


키보드를 표시 할 때 UIScrollView / UITableView 스크롤

거기에 사용할 수있는 몇 가지 방법이 있습니다 :

  1. 키보드 모양 이벤트 알림을 구독하고 오프셋을 수동으로 변경할 수 있습니다.
//Swift 2.0+
override func viewDidLoad() {
    super.viewDidLoad()

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

func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue.size.height {
            tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
        }
    }
}
    
func keyboardWillHide(notification: NSNotification) {
    tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
}

//Objective-C
- (void)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];

}

- (void)keyboardWillShow:(NSNotification *)notification {

    NSDictionary *userInfo = [notification userInfo];

    if (userInfo) {
    
        CGRect keyboardEndFrame;
        [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
        tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardEndFrame.size.height, 0);
    
    }

}

- (void)keyboardWillHide:(NSNotification *)notification {

    tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);

}
  1. 또는 TPKeyboardAvoidingTableView 또는 TPKeyboardAvoidingScrollView와 같은 기성품 솔루션을 사용 하십시오. https://github.com/michaeltyson/TPKeyboardAvoiding

보기에 탭으로 키보드 닫기

키보드 밖에서 탭하여 키보드를 숨기려면이 해킹 트릭을 사용할 수 있습니다 (Objective-C에서만 작동).

- (void)viewDidLoad {
    [super viewDidLoad];

    // dismiss keyboard when tap outside a text field
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self.view action:@selector(endEditing:)];
    [tapGestureRecognizer setCancelsTouchesInView:NO];
    [self.view addGestureRecognizer:tapGestureRecognizer];
}

Swift에는 더 많은 코드가 있습니다.

override func viewDidLoad() {
    super.viewDidLoad()

    // dismiss keyboard when tap outside a text field 
    let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(YourVCName.dismissKeyboard))
    view.addGestureRecognizer(tapGestureRecognizer)
}

//Calls this function when the tap is recognized.
func dismissKeyboard() {
    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)
}

다른 Swift 3 / iOS 10 예제

class vc: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        txtSomeField.delegate = self
    }
}

extension vc: UITextFieldDelegate {
    //Hide the keyboard for any text field when the UI is touched outside of the keyboard.
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
    {
        self.view.endEditing(true) //Hide the keyboard
    }
}

맞춤형 인앱 키보드 만들기

사용자 지정 키보드 애니메이션 GIF

기본 인앱 키보드입니다. 같은 방법으로 키보드 레이아웃을 만들 수 있습니다. 다음은 수행해야 할 주요 사항입니다.

  • 소유자가 UIView 하위 클래스 인 Swift 또는 Objective-C 클래스 인 .xib 파일에서 자판 배열을 만듭니다.
  • 사용자 정의 키보드를 사용하도록 UITextField 지시하십시오.
  • 대리자를 사용하여 키보드와 기본보기 컨트롤러간에 통신합니다.

.xib 자판 배열 파일을 만듭니다.

  • Xcode에서 파일> 새로 만들기> 파일 ...> iOS> 사용자 인터페이스>보기 로 이동하여 .xib 파일을 만듭니다.
  • 내 Keyboard.xib 전화 했어.
  • 필요한 단추를 추가하십시오.
  • 자동 레이아웃 제약 조건을 사용하여 키보드의 크기에 관계없이 단추의 크기가 그에 맞게 조정됩니다.
  • File 's Owner (루트 뷰가 아닌)를 Keyboard 클래스로 설정합니다. 이것은 일반적인 오류의 원인입니다. 다음 단계에서이 클래스를 만듭니다. 끝에있는 메모를 참조하십시오.

.swift UIView 하위 클래스 키보드 파일 만들기

  • Xcode에서 File> New> File ...> iOS> Source> Cocoa Touch Class 로 이동하여 Swift 또는 Objective-C 클래스를 만듭니다. 새로 생성 된 클래스의 수퍼 클래스로 UIView 선택

  • 나는 내 Keyboard.swift (Objective-C의 Keyboard 클래스)

  • Swift에 다음 코드를 추가합니다.

      import UIKit
    
      // The view controller will adopt this protocol (delegate)
      // and thus must contain the keyWasTapped method
      protocol KeyboardDelegate: class {
          func keyWasTapped(character: String)
      }
    
      class Keyboard: UIView {
      
          // This variable will be set as the view controller so that 
          // the keyboard can send messages to the view controller.
          weak var delegate: KeyboardDelegate?
    
          // MARK:- keyboard initialization
      
          required init?(coder aDecoder: NSCoder) {
              super.init(coder: aDecoder)
              initializeSubviews()
          }
      
          override init(frame: CGRect) {
              super.init(frame: frame)
              initializeSubviews()
          }
      
          func initializeSubviews() {
              let xibFileName = "Keyboard" // xib extention not included
              let view = NSBundle.mainBundle().loadNibNamed(xibFileName, owner: self, options: nil)[0] as! UIView
              self.addSubview(view)
              view.frame = self.bounds
          }
      
          // MARK:- Button actions from .xib file
      
          @IBAction func keyTapped(sender: UIButton) {
              // When a button is tapped, send that information to the 
              // delegate (ie, the view controller)
              self.delegate?.keyWasTapped(sender.titleLabel!.text!) // could alternatively send a tag value
          }
      
      }
    
  • Objective-C에 다음 코드를 추가합니다.

    Keyboard.h 파일

    #import <UIKit/UIKit.h>
    
    // The view controller will adopt this protocol (delegate)
    // and thus must contain the keyWasTapped method
    @protocol KeyboardDelegate<NSObject>
    - (void)keyWasTapped:(NSString *)character;
    @end
    
    @interface Keyboard : UIView
    @property (nonatomic, weak) id<KeyboardDelegate> delegate;  
    @end
    

    Keyboard.m 파일

    #import "Keyboard.h"
    
    @implementation Keyboard
    
    - (id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
        [self initializeSubviews];
        return self;
    }
    
    - (id)initWithFrame:(CGRect)frame {
        self = [super initWithFrame:frame];
        [self initializeSubviews];
        return self;
    }
    
    - (void)initializeSubviews {
        NSString *xibFileName = @"Keyboard"; // xib extention not included
        UIView *view = [[[NSBundle mainBundle] loadNibNamed:xibFileName owner:self options:nil] firstObject];
        [self addSubview:view];
        view.frame = self.bounds;
    }
    
    // MARK:- Button actions from .xib file
    
    -(IBAction)keyTapped:(UIButton *)sender {
        // When a button is tapped, send that information to the
        // delegate (ie, the view controller)
        [self.delegate keyWasTapped:sender.titleLabel.text]; // could alternatively send a tag value
    }
    
    @end
    
  • .xib 파일의 버튼에서 버튼 콜백까지 Swift 또는 Objective-C 소유자의 @IBAction 메소드로 드래그 액션을 제어하여 모두 연결합니다.
  • 프로토콜 및 위임 코드에 유의하십시오. 대리인이 작동하는 방법에 대한 간단한 설명은 이 대답 을 참조하십시오.

보기 컨트롤러 설정

  • 메인 스토리 보드에 UITextField 를 추가하고 IBOutlet 을 사용하여보기 컨트롤러에 연결하십시오. 그것을 textField 합니다.

  • Swift에서 View Controller에 대해 다음 코드를 사용하십시오.

      import UIKit
    
      class ViewController: UIViewController, KeyboardDelegate {
      
          @IBOutlet weak var textField: UITextField!
      
          override func viewDidLoad() {
              super.viewDidLoad()
          
              // initialize custom keyboard
              let keyboardView = Keyboard(frame: CGRect(x: 0, y: 0, width: 0, height: 300))
              keyboardView.delegate = self // the view controller will be notified by the keyboard whenever a key is tapped
          
              // replace system keyboard with custom keyboard
              textField.inputView = keyboardView
          }
      
          // required method for keyboard delegate protocol
          func keyWasTapped(character: String) {
              textField.insertText(character)
          }
      }
    
  • Objective-C에 다음 코드를 사용하십시오.

    .h 파일

    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController
    
    @end
    

    .m 파일

    #import "ViewController.h"
    #import "Keyboard.h"
    
    @interface ViewController ()<KeyboardDelegate>
    
    @property (nonatomic, weak) IBOutlet UITextField *textField;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        // initialize custom keyboard
        Keyboard *keyboardView = [[Keyboard alloc] initWithFrame:CGRectMake(0, 0, 0, 300)];
        keyboardView.delegate = self; // the view controller will be notified by the keyboard whenever a key is tapped
    
        // replace system keyboard with custom keyboard
        self.textField.inputView = keyboardView;
    }
    
    - (void)keyWasTapped:(NSString *)character {
        [self.textField insertText:character];
    }
    
    @end
    
  • View Controller는 앞서 정의한 KeyboardDelegate 프로토콜을 사용합니다.

일반적인 오류

EXC_BAD_ACCESS 오류가 발생하는 것은 nib File 's Owner 에서처럼보기의 사용자 정의 클래스를 Keyboard 로 설정했기 때문일 수 있습니다.

Keyboard.nib 을 선택한 다음 파일 소유자를 선택하십시오.

파일의 소유자 스크린 샷

루트보기의 사용자 정의 클래스가 비어 있는지 확인하십시오.

빈 루트보기 스크린 샷

노트

이 예제는 원래이 스택 오버플로 응답 에서옵니다.

싱글 톤 + 델리게이트를 사용하여 키보드 관리하기

키보드 관리를 처음 시작할 때 각 ViewController에서 별도의 알림을 사용했습니다.

알림 방법 (NSNotification 사용) :

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.keyboardNotification(_:)), name: UIKeyboardWillChangeFrameNotification, object: nil)
    }

    func keyboardNotification(notification: NSNotification) {
        guard let userInfo = notification.userInfo else { return }
    
        let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
        let duration: NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseOut.rawValue
        let animationCurve: UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
    
        if endFrame?.origin.y >= UIScreen.mainScreen().bounds.size.height {
            lowerViewBottomConstraint.constant = 0
        } else {
            lowerViewBottomConstraint.constant = endFrame?.size.height ?? 0.0
        }
        view.animateConstraintWithDuration(duration, delay: NSTimeInterval(0), options: animationCurve, completion: nil)
    }
}

내 문제는 내가 하나의 ViewController마다이 코드를 반복해서 쓰는 것을 발견했다는 것이다. 조금 실험 한 후 Singleton + Delegate 패턴을 사용하여 많은 코드를 재사용하고 모든 키보드 관리를 한 곳에서 구성 할 수있었습니다!

싱글 톤 + 위임 방법 :

protocol KeyboardManagerDelegate: class {
    func keyboardWillChangeFrame(endFrame: CGRect?, duration: NSTimeInterval, animationCurve: UIViewAnimationOptions)
}

class KeyboardManager {

    weak var delegate: KeyboardManagerDelegate?

    class var sharedInstance: KeyboardManager {
        struct Singleton {
            static let instance = KeyboardManager()
        }
        return Singleton.instance
    }

    init() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(KeyboardManager.keyboardWillChangeFrameNotification(_:)), name: UIKeyboardWillChangeFrameNotification, object: nil)
    }

    @objc func keyboardWillChangeFrameNotification(notification: NSNotification) {
        guard let userInfo = notification.userInfo else { return }
    
        let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
        let duration: NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseOut.rawValue
        let animationCurve: UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
    
        delegate?.keyboardWillChangeFrame(endFrame, duration: duration, animationCurve: animationCurve)
    }
}

이제 ViewController에서 키보드를 관리하려면 해당 ViewController에 대한 대리자를 설정하고 모든 대리자 메서드를 구현해야합니다.

class ViewController: UIViewController {
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        KeyboardManager.sharedInstance.delegate = self
    }
}

// MARK: - Keyboard Manager

extension ViewController: KeyboardManagerDelegate {
    func keyboardWillChangeFrame(endFrame: CGRect?, duration: NSTimeInterval, animationCurve: UIViewAnimationOptions) {
        if endFrame?.origin.y >= UIScreen.mainScreen().bounds.size.height {
           lowerViewBottomConstraint.constant = 0
        } else {
            lowerViewBottomConstraint.constant = (endFrame?.size.height ?? 0.0)
        }
        view.animateConstraintWithDuration(duration, delay: NSTimeInterval(0), options: animationCurve, completion: nil)
    }
}

이 방법은 매우 사용자 정의 할 수 있습니다! UIKeyboardWillHideNotification 대한 기능을 추가하고 싶다고 UIKeyboardWillHideNotification . 이것은 KeyboardManagerDelegate 메소드를 추가하는 것만큼이나 쉽습니다.

KeyboardManagerDelegateUIKeyboardWillHideNotification :

protocol KeyboardManagerDelegate: class {
    func keyboardWillChangeFrame(endFrame: CGRect?, duration: NSTimeInterval, animationCurve: UIViewAnimationOptions)
    func keyboardWillHide(notificationUserInfo: [NSObject: AnyObject])
}

class KeyboardManager {
    init() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(KeyboardManager.keyboardWillChangeFrameNotification(_:)), name: UIKeyboardWillChangeFrameNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(KeyboardManager.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
    }

    func keyboardWillHide(notification: NSNotification) {
        guard let userInfo = notification.userInfo else { return }
        delegate?.keyboardWillHide(userInfo)
    }
}

하나의 ViewController에 func keyboardWillHide(notificationUserInfo: [NSObject: AnyObject]) 만 구현하려고한다고 가정 func keyboardWillHide(notificationUserInfo: [NSObject: AnyObject]) . 이 방법을 선택적으로 만들 수도 있습니다.

typealias KeyboardManagerDelegate = protocol<KeyboardManagerModel, KeyboardManagerConfigureable>

protocol KeyboardManagerModel: class {
    func keyboardWillChangeFrame(endFrame: CGRect?, duration: NSTimeInterval, animationCurve: UIViewAnimationOptions)
}

@objc protocol KeyboardManagerConfigureable {
    optional func keyboardWillHide(userInfo: [NSObject: AnyObject])
}

*이 패턴은 @objc 남용을 피하는 데 도움이됩니다. 자세한 내용은 http://www.jessesquires.com/avoiding-objc-in-swift/ 를 참조하십시오!

요약하면, Singleton + Delegate를 사용하여 키보드를 관리하는 것이 알림을 사용하는 것보다 효율적이고 사용하기 쉽다는 것을 알았습니다.

키보드가있을 때 위 또는 아래로보기 이동

참고 : 이 기능은 iOS에서 제공하는 내장 키보드에서만 작동합니다.

빠른:

UIViewController 의 뷰가 표시 될 때 프레임의 원점을 늘리고 숨겨진 경우 축소 시키려면 클래스에 다음 함수를 추가합니다.

func keyboardWillShow(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0{
            self.view.frame.origin.y -= keyboardSize.height
        }
    }

}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y != 0{
            self.view.frame.origin.y += keyboardSize.height
        }
    }
}

그리고 클래스의 viewDidLoad() 메서드에서 다음 옵저버를 추가합니다.

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

그리고 이것은 키보드의 height 속성을 사용하여 모든 화면 크기에서 작동합니다.


목표 -C :

Objective-C에서 같은 작업을 수행하기 위해이 코드를 사용할 수 있습니다.

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification
{
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    [UIView animateWithDuration:0.3 animations:^{
        CGRect f = self.view.frame;
        f.origin.y = -keyboardSize.height;
        self.view.frame = f;
    }];
}

-(void)keyboardWillHide:(NSNotification *)notification
{
    [UIView animateWithDuration:0.3 animations:^{
        CGRect f = self.view.frame;
        f.origin.y = 0.0f;
        self.view.frame = f;
    }];
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow