UITableView의 배경을 터치하여 키보드 닫기


105

나는이 UITableView와 함께 UITextField세포로의. 의 배경을 UITableView터치 하면 키보드를 닫고 싶습니다 . UIButton의 크기를 만들고 UITableView뒤에 배치 하여이 작업을 수행하려고 합니다 UITableView. 유일한 문제는 UIButton터치가 UITableView에있을 때도 모든 터치를 잡는 것입니다. 내가 뭘 잘못하고 있죠?

감사!


관련 질문 및 답변 : Q1 , Q2 , Q3 .
Yantao Xie 2012

이것은 최선의 응답입니다 stackoverflow.com/a/12851794/1418457
onmyway133

답변:


203

이는 UITapGestureRecognizer 를 생성하여 쉽게 수행 할 수 있습니다. 객체 (기본적으로 단일 탭에서 "제스처"를 감지하므로 추가 사용자 정의가 필요하지 않음) 제스처가 때 대상 / 액션을 지정한 다음 제스처 인식기 객체를 연결하여 쉽게 수행 할 수 있습니다. 테이블보기에.

예 : 아마도 귀하의 viewDidLoad방법에서 :

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];

그리고 hideKeyboard방법은 다음과 같습니다.

- (void) hideKeyboard {
    [textField1 resignFirstResponder];
    [textField2 resignFirstResponder];
    ...
    ...
}

UITextField개체 내부를 터치 할 때 제스처가 실행되지 않습니다 . 그것은에 불구하고 해고 UITableView배경, 바닥 글보기, 헤더보기에 UILabels등 내부 세포


4
내가 이것을 시도했을 때 나는 테이블이 셀을 선택하는 것을 막았다는 것을 발견했다 :(. 그렇지 않으면 굉장한 해결책
Brian

109
아래의 솔루션은 다음을 설정하여이 작업을 훨씬 더 개선 할 수 gestureRecognizer.cancelsTouchesInView = NO;
있다고 지적

3
tableView에 연결되면 gestureRecognizer를 해제하는 것을 잊지 마십시오.
Paul Lynch

39
위해 hideKeyboard방법, 텍스트 필드와 직접 통신하는 대신 당신이 할 수 있습니다 [self.view endEditing:NO];. Apple 문서에서 : " 이 메서드는 현재 첫 번째 응답자 인 텍스트 필드에 대한 현재보기 및 해당 하위보기 계층을 확인합니다. 하나를 찾으면 해당 텍스트 필드에 첫 번째 응답자로 사임하도록 요청합니다. force 매개 변수가로 설정되면 예, 텍스트 필드는 묻지도 않고 강제로 사임해야합니다. "
Gobot

1
이런 식으로 내 "didSelectRowAtIndexPath"메서드가 호출되지 않습니다. 이것에 대한 해결책?
uniruddh

127

UITapGestureRecognizer 솔루션은 다음을 설정하는 경우 테이블 셀 선택과 함께 작동합니다.

gestureRecognizer.cancelsTouchesInView = NO;

1
아마도 우리는이 대리자 메서드 구현해야합니다,이 셀을 만지지 수 있지만 제스처도 인식shouldReceiveTouch
onmyway133

61

이를 수행하는 가장 좋은 방법은 다음과 같습니다. 그냥 해

[self.view endEditing:YES];

또는

[[self.tableView superView] endEditing:YES];

이 코드를 어디에 넣어야합니까? 초심자 죄송합니다. 그리고 신속한 코드를 제공하십시오.
John

54

Storyboard에서도 수행 할 수 있습니다. 여기에 이미지 설명 입력


1
무엇을 선택하든 : 드래그시 해제, 대화식 해제, 표 셀을 터치하면 선택됩니다. 나는 신속하고 엑스 코드 (8) 3.하시기 바랍니다 도움을 사용하고 있습니다

22

UITableView의 하위 클래스와 마찬가지로 UIScrollView아래에서 하나의 대리자 메서드를 구현하면 매우 쉽고 빠른 솔루션이 제공됩니다. resignFirstResponder뷰 계층 구조가 현재 응답자를 조사하고 현재 응답자를 찾고 응답자 상태를 사임하도록 요청하므로 개입 할 필요도 없습니다 .

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

그리고 UIScrollViewDelegate헤더 파일 에 추가하는 것을 잊지 마십시오.


2
iOS7 이상을 대상으로하는 경우 @Joe Masilotti가 지적한대로이 하나의 라이너를 통해 수행 할 수 있습니다. self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
atulkhatri 2015

키보드를 표시하기 위해 위로 스크롤해야하는 화면 하단의 텍스트 필드를 탭하면 어떻게됩니까? -키보드가 숨겨집니다.
이슬람 Q.

Swift 4 — self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.onDrag
RobLabs 2017

13

먼저 scrollViewWillBeginDragging다음 UIViewController을 추가하여 들어보십시오 UIScrollViewDelegate.

.h 파일에서 :

@interface MyViewController : UIViewController <UIScrollViewDelegate> 

.m 파일에서 :

- (void)scrollViewWillBeginDragging:(UIScrollView *)activeScrollView {

    [self dismissKeyboard];

}

그런 다음 다른 상호 작용을 들어보십시오.

- (void)setupKeyboardDismissTaps {

    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UISwipeGestureRecognizer *swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeDownGestureRecognizer.cancelsTouchesInView = NO;
    swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown;
    [self.tableView addGestureRecognizer:swipeDownGestureRecognizer];

    UISwipeGestureRecognizer *swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeLeftGestureRecognizer.cancelsTouchesInView = NO;
    swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.tableView addGestureRecognizer:swipeLeftGestureRecognizer];

    UISwipeGestureRecognizer *swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeRightGestureRecognizer.cancelsTouchesInView = NO;
    swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
    [self.tableView addGestureRecognizer:swipeRightGestureRecognizer];


    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

그런 다음 구현하십시오 dismissKeyboard.

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    [yourTextFieldPointer resignFirstResponder];

}

나처럼 사용자 정의 테이블 셀 내부의 UITextField에 대한 키보드를 닫고 싶다면 :

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    CustomCellClass *customCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    [customCell.textFieldInCell resignFirstResponder]; 

}

누구나 검색하는 데 도움이되기를 바랍니다!



8

코딩의 즐거움을위한 빠른 버전은 다음과 같습니다.

탭 제스처 인식기를 추가 한 다음 키보드를 닫습니다. TextField에 대한 콘센트가 필요하지 않습니다!

override func viewDidLoad() {
    super.viewDidLoad()
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))
}

func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .Ended {
        view.endEditing(true)
    }
    sender.cancelsTouchesInView = false
}

1
이것은 사용자 정의 tableViewCell에서도 작동합니다! 나는 이것을 알아 내기 위해 너무 많은 시간을 보냈다. 정말 고맙습니다! 너는 나의 영웅이야. youtu.be/EqWRaAF6_WY
peacetype

8

셀 탭을 차단하지 않는 Swift 3 버전이 있습니다.

에서 viewDidLoad()방법 :

let dismissKeyboardGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
dismissKeyboardGesture.cancelsTouchesInView = false
tableView.addGestureRecognizer(dismissKeyboardGesture)

그리고 hideKeyboard다음과 같이 보입니다.

func hideKeyboard() {
    view.endEditing(true)
}

7

나는 이렇게했다 :

TableViewController에서 첫 번째 응답자를 비활성화하는 메서드를 만듭니다 (해당 시점에서 TextBox가 됨).

- (BOOL)findAndResignFirstResonder:(UIView *)stView {
    if (stView.isFirstResponder) {
        [stView resignFirstResponder];
        return YES;     
    }

    for (UIView *subView in stView.subviews) {
        if ([self findAndResignFirstResonder:subView]) {
            return YES;
        }
    }
    return NO;
}

년은 tableView:didSelectRowAtIndexPath:이전 메소드를 호출합니다

- (void)tableView:(UITableView *)tableView
                             didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    [self findAndResignFirstResonder: self.view];
    ...
}

당신은 당신이 요구하는 방식으로 잘못하고 있습니다. 뷰에 버튼을

2
테이블 뷰 셀 내부 (및 해당 테이블 뷰 셀 내의 UITextField 외부)를 탭하면 멋지게 작동합니다. 그러나 테이블 뷰의 배경을 탭하면 (종종 더 쉽게 도달 할 수있는 대상이됩니다-예이 Fitts의 법칙!), 그런 행운은 없습니다. 사실, tableView : didSelectRowAtIndexPath : 내에서이 작업을 수행하고 있기 때문에 예상됩니다. 테이블 뷰의 다른 곳을 탭하여 작동하도록 조정될 수 있다면 (그렇지 않으면 키보드 포커스를 원하지 않을 것입니다) 여기에서 승자가 된 것 같습니다!
Joe D' Andrea

jdandrea와 같은 문제가 있습니다. 즉 didSelectRowAtIndexPath당신이있는 TableView 자체를 눌러 실행되지 않습니다.
zekel 2010-06-30

didSelectRowAtIndexPath가 충분하지 않으면 touchesBegan에서도 동일하게 수행하십시오!
Amogh Talpallikar

5

나는 가지고 UITableViewController있고 구현 touchesBegan:withEvent:이 작동하지 않았습니다.

효과는 다음과 같습니다.

빠른:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    view.endEditing(true)
}

목표 -C :

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.view endEditing:YES];
}

좋은 생각이에요. 좋아요.
HotFudgeSunday

4
@interface DismissableUITableView : UITableView {
}
@end

@implementation DismissableUITableView

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 [self.superview endEditing:YES];
 [super touchesBegan:touches withEvent:event];
}

@end

그런 다음 Nib 파일에서 UITableView의 유형을 DismissableUITableView로 설정했는지 확인하십시오. .....이 클래스에 대해 더 나은 이름을 생각할 수 있었을 수도 있지만 요점을 알 수 있습니다.


4

iOS7을 대상으로하는 경우 다음 중 하나를 사용할 수 있습니다.

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

전자는 테이블보기가 스크롤 될 때 화면에서 키보드를 애니메이션하고 나중에 주식 메시지 앱처럼 키보드를 숨 깁니다.

이러한에서 참고 UIScrollView하는 UITableView에서 상속됩니다.


좋은. 나는 키보드가 아래로 움직이기 시작할 때까지 화면의 높은 곳에서 아래로 스 와이프 한 다음 키보드가 약간 위로 움직일 때까지 위로 스 와이프 한 다음 놓아서 일종의 깨뜨릴 수있었습니다. scrollview가 정상으로 돌아 오지 않습니다.
Sam

3

이 시도:

viewDidLoad(){

    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))

    tableView.addGestureRecognizer(tap)

}
//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {

    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)

}

2

UITableView는 UIScrollView의 하위 클래스입니다.

내가 한 방법은 사용자의 스크롤 이벤트를 수신 한 다음 ResignFirstResponder를 사용하는 것입니다. 다음은 코드에서 구현할 UIScrollViewDelegate 메서드입니다.

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

이러한 종류의 문제에 접근 할 때 가장 좋은 방법은 각 개체와 부모 클래스 (이 경우 UITableViewDelegate, UIScrollViewDelegate)에 대한 대리자 프로토콜을 조사하는 것입니다. NS 개체가 실행하는 이벤트 수는 상당히 크고 포괄적입니다. 프로토콜을 쉽게 구현 한 다음 모든 것을 서브 클래 싱합니다.


2

나는 같은 문제가 있었고 여기에 내 해결책이 있습니다.

구현 한보기 또는보기 컨트롤러에서 <UITextFieldDelegate>

(제 경우에는 UITableViewCell TextFieldCell이라는 ),

UITapGestureRecognizer속성으로 선언 :

@interface TextFieldCell : UITableViewCell <UITextFieldDelegate>
{
    UITextField *theTextField;
    UITapGestureRecognizer *gestureRecognizer;
}
@property (nonatomic,retain) UITextField *theTextField;
@property (nonatomic,retain) UITapGestureRecognizer *gestureRecognizer; 

뷰 / 컨트롤러에서 초기화합니다.

self.gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboard:)];

- (void)textFieldDidBeginEditing:(UITextField *)textField메서드에서 사용 superView하여 tableView로 이동하고 다음을 호출하십시오 addGestureRecognizer.

[self.superview.superview addGestureRecognizer:gestureRecognizer];

그리고에 - (void)textFieldDidEndEditing:(UITextField *)textField그냥 제스처 인식기를 제거합니다 :

[self.superview.superview removeGestureRecognizer:gestureRecognizer];

도움이되기를 바랍니다.


이것은 나를 위해 해냈습니다. 감사합니다 hac.jack
gilsaints88

2

셀의 일부가 선택되면 내 셀이 키보드를 열고 셀의 아무 곳이나 클릭하면 닫히기를 원했습니다. 키보드를 열려면 :

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    if (selected)
    {
        [self.textField becomeFirstResponder];
    }
}

(참고 : 셀을 서브 클래 싱했지만 다음의 tableView:didSelectRowAtIndexPath:델리게이트 메서드 에서 쉽게 달성 할 수 있습니다.UITableView )

이렇게하면 최상위 솔루션에서 셀을 두 번 클릭하면 키보드가 흔들리는 것처럼 먼저 제스처 인식기가 키보드를 닫으려고 시도하고 두 번째 셀이 다시 선택되어 키보드를 열려고 시도했습니다.

해결책은 현재 선택된 셀 내에서 클릭이 발생했는지 확인하는 것입니다.

- (void)viewDidLoad
{
    [super viewDidLoad];
    //gesture recognizer to close the keyboard when user taps away
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard:)];
    tap.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tap];
}

-(void)dismissKeyboard:(UIGestureRecognizer*)tapGestureRecognizer
{
    if (!CGRectContainsPoint([self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]].frame, [tapGestureRecognizer locationInView:self.tableView]))
    {
        [self.view endEditing:YES];
    }
}

2

잘 작동하는 솔루션을 찾았습니다.

UIGestureRecognizerDelegate 및 메소드 – gestureRecognizer : shouldReceiveTouch : 를 사용하는 데 필요합니다 .

다음과 같이 제스처 인식기를 TableView에 추가합니다.

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
tapGestureRecognizer.delegate = self;
[self.suggestedTableView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

그런 다음 UITableViewCell 클래스에서 수행되는 터치를 거부 하는 shouldReceiveTouch 대리자 메서드를 구현합니다 . hideKeyboard의 터치가있는 UITableViewCell 클래스 외부에서 수행 된 경우 메서드는 호출됩니다.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if([touch.view isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCell
    if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
    if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    return YES; // handle the touch
}

- (void) hideKeyboard{
    [textField resignFirstResponder];
}

2

UITableViewbackgroundViewSwift에서 아래와 같이 셀 선택을 엉망으로 만들지 않고이 동작을 달성 한 편리한 속성이 있습니다.

let tableBackTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
tableView.backgroundView = UIView()
tableView.backgroundView?.addGestureRecognizer(tableBackTapRecognizer)


1

단순히 UITapGestureRecognizer를 사용하면 cancelsTouchesInView = NO셀과 UITextView를 탭하면 숨기기도 트리거됩니다. UITextView가 여러 개 있고 다음 항목을 탭하면 좋지 않습니다. 키보드가 숨기기 시작하고 다음 textView가 firstResponder가되고 키보드가 다시 표시됩니다. 이를 방지하려면 탭 위치를 확인하고 탭이 셀에없는 경우에만 키보드를 숨 깁니다.

// init
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapTableView:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapRecognizer];


// Hide on tap
- (void)didTapTableView:(UITapGestureRecognizer *)tap
{
    CGPoint point = [tap locationInView:tap.view];
    [self.view endEditing:!CGRectContainsPoint([self.tableView rectForRowAtIndexPath:[self.tableView indexPathForRowAtPoint:point]], point)];
}

의 순서를 scrollViewWillBeginDragging:트리거하기 위해,있는 tableView의 scrollEnabled속성이 있어야합니다YES

// Hide on scroll
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

나 한테 딱이야. tableview 셀에 texbox를 추가했습니다. 키보드 외부를 터치하면 닫힙니다
Nicola

0

텍스트 필드로 가득 찬 표를 만드는 이유는 무엇입니까? 텍스트 필드를 포함하는 각 행에 대해 상세보기를 사용해야합니다. 세부보기를 푸시 할 때 사용자가 테이블 목록에서 클릭 한 번으로 편집을 시작할 수 있도록 "[myTextField becomeFirstResponder]"를 호출해야합니다.


Apple의 연락처 앱은이 작업을 정확하게 수행합니다. 텍스트 필드 자체로 가득 차 있다고 말하지는 않지만 좋은 효과를 내기 위해 사용합니다.
Joe D' Andrea

2
테이블보기에서 텍스트를 인라인으로 편집하는 것은 사용자가 편집하려는 모든 텍스트 필드에 대해 세부 정보보기를 푸시하는 것보다 훨씬 빠르고 직관적입니다. 가장 가까운 HTML 양식이나 iPhone 환경 설정 패널의 텍스트 필드 또는 연락처 앱을 요청하거나 등 등 ... 애플이 이것을 표준 셀 유형으로 만들지 않은 것은 정말 부끄러운 일이지만이를 달성하는 것에 대한 웹에는 많은 정보가 있습니다.
glenc 2010 년

0

테이블 뷰를 서브 클래스 (ugh!)하려는 경우 다음과 같이 작동 할 수 있습니다.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

   BOOL backgroundTouched = YES;

   for (UITouch *touch in touches) {
      CGPoint location = [touch locationInView:self];
      for (UITableViewCell *cell in self.visibleCells) {
         if (CGRectContainsPoint(cell.frame, location)) {
            backgroundTouched = NO;
            break;
         }
      }
   }

   if (backgroundTouched) {
      for (UITableViewCell *cell in self.visibleCells) {
         // This presumes the first subview is the text field you want to resign.
         [[cell.contentView.subviews objectAtIndex:0] resignFirstResponder];
      }
   }

   [super touchesBegan:touches withEvent:event];
}

0

리턴 키를 누른 상태에서 키보드를 해제하려면 textField에 다음 코드를 추가하면됩니다.

- (BOOL)textFieldShouldReturn:(UITextField *)atextField
{
   [textField resignFirstresponder];
}

일부 텍스트 필드에는 선택기 뷰 또는 다른 일부가 하위 뷰로있을 수 있으므로 위의 메서드가 작동하지 않으므로 UITapGestureRecognizer 클래스를 사용해야합니다. 즉, viewDidLoad 메서드에 다음 코드 스 니펫을 추가합니다.

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard)];

    [self.view addGestureRecognizer:tap];

이제 resign 응답자를 선택기 메소드에 추가하기 만하면됩니다.

-(void)dismissKeyboard 
{
    [textField resignFirstResponder];
}

도움이되기를 바랍니다, 감사합니다 :)


0

많은 흥미로운 답변. UITableView 시나리오에 가장 적합하다고 생각하는 솔루션에 다른 접근 방식을 컴파일하고 싶습니다 (일반적으로 사용하는 시나리오) : 일반적으로 원하는 것은 기본적으로 두 가지 시나리오에서 키보드를 숨기는 것입니다. 텍스트 UI 요소 외부를 탭할 때, 또는 UITableView를 아래 / 위로 스크롤합니다. 첫 번째 시나리오는 TapGestureRecognizer를 통해 쉽게 추가 할 수 있고 두 번째 시나리오는 UIScrollViewDelegate scrollViewWillBeginDragging : 메소드를 통해 추가 할 수 있습니다. 비즈니스의 첫 번째 순서, 키보드를 숨기는 방법 :

   /**
     *  Shortcut for resigning all responders and pull-back the keyboard
     */
    -(void)hideKeyboard
    {
        //this convenience method on UITableView sends a nested message to all subviews, and they resign responders if they have hold of the keyboard
        [self.tableView endEditing:YES];

    }

이 메서드는 UITableView 뷰 계층 구조 내 하위 뷰의 textField UI를 사임하므로 모든 단일 요소를 독립적으로 사임하는 것보다 더 실용적입니다.

다음으로 외부 탭 제스처를 통해 해제를 처리합니다.

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self setupKeyboardDismissGestures];

}

- (void)setupKeyboardDismissGestures
{

//    Example for a swipe gesture recognizer. it was not set-up since we use scrollViewDelegate for dissmin-on-swiping, but it could be useful to keep in mind for views that do not inherit from UIScrollView
//    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
//    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
//    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
//    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
    //this prevents the gestureRecognizer to override other Taps, such as Cell Selection
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

tapGestureRecognizer.cancelsTouchesInView를 NO로 설정하면 gestureRecognizer가 UITableView의 정상적인 내부 작업을 재정의하는 것을 방지 할 수 있습니다 (예 : 셀 선택을 방해하지 않음).

마지막으로 UITableView를 위 / 아래로 스크롤 할 때 키보드 숨기기를 처리하려면 UIScrollViewDelegate 프로토콜 scrollViewWillBeginDragging : 메서드를 다음과 같이 구현해야합니다.

.h 파일

@interface MyViewController : UIViewController <UIScrollViewDelegate>

.m 파일

#pragma mark - UIScrollViewDelegate

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self hideKeyboard];
}

도움이 되었기를 바랍니다. =)


0

내가 마침내 작품을 만든 방법은 다음과 같습니다. 나는 다른 답변의 제안과 코드를 결합했습니다. 기능 : "다음"및 "완료"키보드 반환 유형을 편집하고 설정하는 동안 키보드 해제, 키보드 위로 텍스트 필드 이동. 더 많은 필드로 "..."바꾸기

static const CGFloat ANIMATION_DURATION = 0.4;
static const CGFloat LITTLE_SPACE = 5;
CGFloat animatedDistance;
CGSize keyboardSize;

@interface ViewController () <UITextFieldDelegate>
 @property (weak, nonatomic) IBOutlet UITextField *firstNameTXT;
  .....// some other text fields
 @property (weak, nonatomic) IBOutlet UITextField *emailTXT;
@end

@implementation ViewController
- (void)viewDidLoad{
.....
// add tap gesture to help in dismissing keyboard
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(tapScreen:)];// outside textfields

[self.view addGestureRecognizer:tapGesture];

// set text fields return key type to Next, last text field to Done
[self.firstNameTXT setReturnKeyType:UIReturnKeyNext];
.....
[self.emailTXT setReturnKeyType:UIReturnKeyDone];

// set text fields tags
[self.firstNameTXT setTag:0];
....// more text fields
[self.emailTXT setTag:5];

// add keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self     selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self      selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}

// dismiss keyboard when tap outside text fields
- (IBAction)tapScreen:(UITapGestureRecognizer *)sender {
  if([self.firstNameTXT isFirstResponder])[self.firstNameTXT resignFirstResponder];
  ...
  if([self.emailTXT isFirstResponder])[self.emailTXT  resignFirstResponder];

  }
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
   if(textField.returnKeyType==UIReturnKeyNext) {
     // find the text field with next tag
     UIView *next = [[textField superview] viewWithTag:textField.tag+1];
     [next becomeFirstResponder];
   } else if (textField.returnKeyType==UIReturnKeyDone || textField.returnKeyType==UIReturnKeyDefault) {
    [textField resignFirstResponder];
 }
return YES;
}

// Moving current text field above keyboard
-(BOOL) textFieldShouldBeginEditing:(UITextField*)textField{
   CGRect viewFrame = self.view.frame;
   CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
   CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
   CGFloat textFieldBottomLine = textFieldRect.origin.y + textFieldRect.size.height + LITTLE_SPACE;//

   CGFloat keyboardHeight = keyboardSize.height;

   BOOL isTextFieldHidden = textFieldBottomLine > (viewRect.size.height - keyboardHeight)? TRUE :FALSE;
  if (isTextFieldHidden) {
    animatedDistance = textFieldBottomLine - (viewRect.size.height - keyboardHeight) ;
    viewFrame.origin.y -= animatedDistance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
  return YES;
}

-(void) restoreViewFrameOrigionYToZero{
  CGRect viewFrame = self.view.frame;
  if (viewFrame.origin.y != 0) {
    viewFrame.origin.y = 0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
}

-(void)keyboardDidShow:(NSNotification*)aNotification{
   NSDictionary* info = [aNotification userInfo];
   keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
 }

-(void)keyboardDidHide:(NSNotification*)aNotification{
   [self restoreViewFrameOrigionYToZero];// keyboard is dismissed, restore frame view to its  zero origin
}
@end

0

@mixca의 대답은 매우 유용하지만 UITextField와 다른 점이 있다면 어떨까요? 재귀 함수로 메인 뷰의 모든 하위 뷰를 검색하여 처리하는 가장 좋은 방법이라고 생각합니다. 아래 예제를 확인하십시오.

- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
    [self resignFirstResponder];
    return YES;
}

    for (UIView *subView in self.subviews) {
        if ([subView findAndResignFirstResponder]) {
            return YES;
        }
    }
    return NO;
}

또한이 메서드를 유틸리티 클래스에 넣을 수 있으며 @mixca의 대답과 같은 탭 제스처에서 사용할 수 있습니다.


0

스위프트 4 / 4.2 / 5

다른 작업을 수행하기 전에 셀을 탭할 때 키보드를 닫을 수도 있습니다.

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    view.endEditing(true)
    // Do something here
    }

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.