UITextField: 키보드가 나타날 때 보기 이동
저는 현재 입력을 위한 여러 UITextFields가 있는 단일 보기가 있는 iPhone 응용 프로그램에서 작업하고 있습니다. 키보드가 표시되면 하단 텍스트 필드를 오버레이합니다. 그래서 textFieldDidBeginEditing:
보기를 위로 이동하기 위해 해당 메서드를 추가했습니다 .
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if ( ( textField != inputAmount ) && ( textField != inputAge ) ) {
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y -= kOFFSET_FOR_KEYBOARD;
frame.size.height += kOFFSET_FOR_KEYBOARD;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}
}
이 메서드는 메시지의 원본이 키보드가 표시될 때 표시되는 텍스트 필드 중 하나인지 확인하고 그렇지 않은 경우 보기를 위로 이동합니다.
또한 textFieldDidEndEnditing:
뷰를 다시 아래로 이동하고 변경된 입력에 따라 일부 모델 객체를 업데이트 하는 메서드를 추가했습니다 .
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ( ( textField != inputMenge ) && ( textField != inputAlter ) ) {
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += kOFFSET_FOR_KEYBOARD;
frame.size.height -= kOFFSET_FOR_KEYBOARD;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}
// Additional Code
}
그러나 이 솔루션에는 간단한 결함이 있습니다. "숨겨진" 텍스트 필드 중 하나를 편집하고 다른 텍스트 필드를 터치하면 키보드가 사라지고 보기가 아래로 이동하고 보기가 다시 위로 이동하고 키보드가 다시 나타납니다.
두 편집 사이에 키보드가 사라지고 다시 나타나지 않도록 할 가능성이 있습니까? )?
이 솔루션은 ComSubVie의 솔루션을 기반으로 합니다.
장점:
- 장치 회전을 지원합니다. 모든 방향에서 작동합니다.
- 애니메이션 지속 시간 및 곡선 값을 하드코딩하지 않고 키보드 알림에서 읽습니다.
- 키보드 애니메이션과 사용자 지정 작업을 동기화하는
UIKeyboardWillShowNotification
대신 활용 합니다UIKeyboardDidShowNotification
. - 더 이상 사용되지 않는
UIKeyboardBoundsUserInfoKey
; - 국제 키 누름으로 인한 키보드 크기 조정을 처리합니다.
- 키보드 이벤트 등록을 취소하여 메모리 누수를 수정했습니다.
- 모든 키보드 처리 코드는 별도의 클래스에 캡슐화되어 있습니다
KBKeyboardHandler
. - 유연성 -
KBKeyboardHandler
특정 요구에 더 잘 맞도록 클래스를 쉽게 확장/수정할 수 있습니다.
제한 사항:
- iOS 4 이상에서 작동하며 이전 버전을 지원하려면 약간의 수정이 필요합니다.
- 단일
UIWindow
. 여러 UIWindows를 사용하는 경우retrieveFrameFromNotification:
메서드 를 수정해야 할 수 있습니다 .
용법:
프로젝트에 KBKeyboardHandler.h, KBKeyboardHandler.m 및 KBKeyboardHandlerDelegate.h를 포함합니다. KBKeyboardHandlerDelegate
보기 컨트롤러에서 프로토콜을 구현하십시오 . 단일 메소드로 구성되며 키보드가 표시되거나 숨겨지거나 크기가 변경될 때 호출됩니다. KBKeyboardHandler
대리자를 인스턴스화 하고 설정합니다(일반적으로 자체). 아래 샘플을 참조하십시오 MyViewController
.
KBKeyboardHandler.h :
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol KBKeyboardHandlerDelegate;
@interface KBKeyboardHandler : NSObject
- (id)init;
// Put 'weak' instead of 'assign' if you use ARC
@property(nonatomic, assign) id<KBKeyboardHandlerDelegate> delegate;
@property(nonatomic) CGRect frame;
@end
KBKeyboardHandler.m :
#import "KBKeyboardHandler.h"
#import "KBKeyboardHandlerDelegate.h"
@implementation KBKeyboardHandler
- (id)init
{
self = [super init];
if (self)
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
@synthesize delegate;
@synthesize frame;
- (void)keyboardWillShow:(NSNotification *)notification
{
CGRect oldFrame = self.frame;
[self retrieveFrameFromNotification:notification];
if (oldFrame.size.height != self.frame.size.height)
{
CGSize delta = CGSizeMake(self.frame.size.width - oldFrame.size.width,
self.frame.size.height - oldFrame.size.height);
if (self.delegate)
[self notifySizeChanged:delta notification:notification];
}
}
- (void)keyboardWillHide:(NSNotification *)notification
{
if (self.frame.size.height > 0.0)
{
[self retrieveFrameFromNotification:notification];
CGSize delta = CGSizeMake(-self.frame.size.width, -self.frame.size.height);
if (self.delegate)
[self notifySizeChanged:delta notification:notification];
}
self.frame = CGRectZero;
}
- (void)retrieveFrameFromNotification:(NSNotification *)notification
{
CGRect keyboardRect;
[[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardRect];
self.frame = [[UIApplication sharedApplication].keyWindow.rootViewController.view convertRect:keyboardRect fromView:nil];
}
- (void)notifySizeChanged:(CGSize)delta notification:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
UIViewAnimationOptions curve;
[[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve];
NSTimeInterval duration;
[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration];
void (^action)(void) = ^{
[self.delegate keyboardSizeChanged:delta];
};
[UIView animateWithDuration:duration
delay:0.0
options:curve
animations:action
completion:nil];
}
@end
KBKeyboardHandlerDelegate.h :
@protocol KBKeyboardHandlerDelegate
- (void)keyboardSizeChanged:(CGSize)delta;
@end
샘플 MyViewController.h :
@interface MyViewController : UIViewController<KBKeyboardHandlerDelegate>
...
@end
샘플 MyViewController.m :
@implementation MyViewController
{
KBKeyboardHandler *keyboard;
}
- (void)dealloc
{
keyboard.delegate = nil;
[keyboard release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
keyboard = [[KBKeyboardHandler alloc] init];
keyboard.delegate = self;
}
- (void)viewDidUnload
{
[super viewDidUnload];
keyboard.delegate = nil;
[keyboard release];
keyboard = nil;
}
- (void)keyboardSizeChanged:(CGSize)delta
{
// Resize / reposition your views here. All actions performed here
// will appear animated.
// delta is the difference between the previous size of the keyboard
// and the new one.
// For instance when the keyboard is shown,
// delta may has width=768, height=264,
// when the keyboard is hidden: width=-768, height=-264.
// Use keyboard.frame.size to get the real keyboard size.
// Sample:
CGRect frame = self.view.frame;
frame.size.height -= delta.height;
self.view.frame = frame;
}
업데이트: iOS 7 경고를 수정했습니다. @weienv에게 감사드립니다.
방금 이 문제를 해결했습니다. 이 용액의 조합 UIKeyboardDidShowNotification
과 UIKeyboardDidHideNotification
상기와 관찰자 textFieldDidBeginEditing:
와 textFieldDidEndEditing:
방법에 관한 것이다.
세 개의 추가 변수가 필요합니다. 하나는 현재 선택된 UITextField(activeField로 이름 지정)를 저장하기 위한 것이고, 하나는 현재 보기가 이동되었는지 여부를 나타내는 변수이고, 다른 하나는 키보드가 표시되는지 여부를 나타내는 변수입니다.
UITextField
이제 두 개의 대리자 메서드가 다음과 같이 표시됩니다.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
activeField = nil;
// Additional Code
}
보기가 로드되면 다음 두 관찰자가 생성됩니다.
- (void)viewDidLoad {
// Additional Code
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification
object:nil];
}
그리고 해당 메소드는 다음과 같이 구현됩니다.
- (void)keyboardWasShown:(NSNotification *)aNotification {
if ( keyboardShown )
return;
if ( ( activeField != inputAmount ) && ( activeField != inputAge ) ) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y -= keyboardSize.height-44;
frame.size.height += keyboardSize.height-44;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
}
keyboardShown = YES;
}
- (void)keyboardWasHidden:(NSNotification *)aNotification {
if ( viewMoved ) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += keyboardSize.height-44;
frame.size.height -= keyboardSize.height-44;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
keyboardShown = NO;
}
이 코드는 이제 예상대로 작동합니다. 키보드는 완료 버튼을 누를 때만 닫힙니다. 그렇지 않으면 키보드가 계속 표시되고 보기가 이동하지 않습니다.
추가 참고 사항으로, 이미 유사한 솔루션을 사용했지만 작동하지 않았기 때문에 개체 animationDuration
를 요청 하여 동적으로 얻을 수 있다고 생각합니다 NSNotification
(지금 하고 있음).
이 보기 컨트롤러는 UITextView
대리인이어야 하며 다음 self.textview.delegate = self
에서 설정해야 합니다 .viewdidload
-(void) textViewDidBeginEditing:(UITextView *)textView
{
NSLog(@"%f",self.view.frame.origin.y);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25f];
CGRect frame = self.view.frame;
frame.origin.y =frame.origin.y -204;
[self.view setFrame:frame];
[UIView commitAnimations];
}
-(void) textViewDidEndEditing:(UITextView *)textView
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25f];
CGRect frame = self.view.frame;
frame.origin.y = frame.origin.y + 204;
[self.view setFrame:frame];
[UIView commitAnimations];
}
UIScrollview에 콘센트를 제공하기만 하면 문제가 해결됩니다. 보기의 각 텍스트 필드에 대해 고유한 태그 속성을 설정합니다.
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
switch (textField.tag)
{
case 2: //can be your textfiled tag
{ CGPoint scrollPoint = CGPointMake(0, yourtextfield.frame.origin.y-150);
//set figure y-150 as per your comfirt
[scrollview setContentOffset:scrollPoint animated:YES];
}break;
case 3:
{ CGPoint scrollPoint = CGPointMake(0, yourtextfield.frame.origin.y-180);
//set figure y-180 as per your comfirt
[scrollview setContentOffset:scrollPoint animated:YES];
}break;
...
}
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
if(textField.tag==3){
[scrollview setContentOffset:CGPointZero animated:YES];
}
//set the last textfield when you want to disappear keyboard.
}
Write below code in your view controller. tbl is your table view.
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
[[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
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
#pragma mark - Keyboard Methods
-(void)keyboardWillShow:(NSNotification *)notification
{
// 375 × 667 ( 750 × 1334 ) iPhone 6
//414 × 736
CGRect keyboardRect = [[[notification userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
int H = [[UIScreen mainScreen] bounds].size.height - 64- 20 -keyboardRect.size.height;
[UIView animateWithDuration:0.5 animations:^{
tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, H, tbl.contentInset.right);
}];
}
-(void)keyboardWillChangeFrame:(NSNotification *)notification
{
CGRect keyboardRect = [[[notification userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
// int H = IS_IPHONE_5?504-keyboardRect.size.height:416-keyboardRect.size.height;
int H = [[UIScreen mainScreen] bounds].size.height - 64- 20 -keyboardRect.size.height;
[UIView animateWithDuration:0.5 animations:^{
// scroll.frame = rect;
tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, H, tbl.contentInset.right);
}];
}
-(void)keyboardWillHide:(NSNotification *)notification
{
[UIView animateWithDuration:0.3 animations:^{
// scroll.frame = rect;
tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, 0, tbl.contentInset.right);
}];
}
매우 쉬운 솔루션, 모든 화면 크기에서 작동
먼저 UITextFields를 UIScrollView에 포함해야 합니다. 제 경우에는 여러 UITextFields와 UITextView가 있었습니다.
그런 다음 UITextFieldDelegate, UITextViewDelegate에서 상속해야 합니다.
class SettingsVC: UIViewController, UITextFieldDelegate, UITextViewDelegate
textfield 및 textview의 대리자를 self에 할당합니다.
fullNameTextField.delegate = self usernameTextField.delegate = self websiteTextField.delegate = self profileDescription.delegate = self
그런 다음 다음 코드를 사용합니다.
var editingTextInput: UIView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardShown(notification:)),
name: NSNotification.Name.UIKeyboardDidShow,
object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
}
func keyboardShown(notification: NSNotification) {
if let infoKey = notification.userInfo?[UIKeyboardFrameEndUserInfoKey],
let rawFrame = (infoKey as AnyObject).cgRectValue {
let keyboardFrame = view.convert(rawFrame, to: view)
let editingTextInputFrame = self.editingTextInput.convert(self.editingTextInput.frame, to: view)
if editingTextInputFrame.maxY > keyboardFrame.minY{
let diff = keyboardFrame.minY - editingTextInputFrame.maxY
containerScrollView.setContentOffset(CGPoint(x: 0, y: -diff), animated: true)
}
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
self.editingTextInput = textField
}
func textViewDidBeginEditing(_ textView: UITextView) {
self.editingTextInput = textView
}
func textFieldDidEndEditing(_ textField: UITextField) {
containerScrollView.setContentOffset(CGPoint.zero, animated: true)
}
func textViewDidEndEditing(_ textView: UITextView) {
containerScrollView.setContentOffset(CGPoint.zero, animated: true)
}
즉, UIKeyboardDidShow 알림을 구독합니다. textField 또는 textView 키보드를 탭하면 키보드의 프레임과 탭한 입력 요소의 프레임을 잡습니다. 이를 viewController의 좌표계로 변환하고 입력 요소의 가장 낮은 지점을 키보드의 가장 높은 지점과 비교합니다. 요소의 하단이 키보드의 가장 높은 부분보다 낮으면 containerScrollView의 오프셋을 그 차이로 설정합니다.
if editingTextInputFrame.maxY > keyboardFrame.minY{
let diff = keyboardFrame.minY - editingTextInputFrame.maxY
containerScrollView.setContentOffset(CGPoint(x: 0, y: -diff), animated: true)
}
ReferenceURL : https://stackoverflow.com/questions/1775860/uitextfield-move-view-when-keyboard-appears
'IT이야기' 카테고리의 다른 글
SSLHandshakeException: Android N/7.0에서 핸드셰이크 실패 (0) | 2021.10.10 |
---|---|
MFMailComposeViewController의 MailComposer 시트에 UIImage를 추가하는 방법 (0) | 2021.10.10 |
다국어 데이터를 보관하기 위한 최적의 데이터베이스 구조 (0) | 2021.10.09 |
C#에서 익명 개체의 속성 반복 (0) | 2021.10.09 |
문자와 혼합된 숫자만 인식하도록 tesseract를 만드는 방법 (0) | 2021.10.09 |