Loại bỏ bàn phím bằng cách chạm vào nền của UITableView


105

Tôi có a UITableViewvới UITextFields là các ô. Tôi muốn loại bỏ bàn phím khi chạm vào nền của bàn phím UITableView. Tôi đang cố gắng làm điều này bằng cách tạo ra một UIButtonkích thước bằng UITableViewvà đặt nó phía sau UITableView. Vấn đề duy nhất UIButtonlà bắt tất cả các lần chạm ngay cả khi chạm trên UITableView. Tôi đang làm gì sai?

Cảm ơn!


Câu hỏi và câu trả lời đã phát hành: Q1 , Q2 , Q3 .
Yantao Xie

Đây là câu trả lời tốt nhất stackoverflow.com/a/12851794/1418457
onmyway133

Câu trả lời:


203

Điều này có thể dễ dàng thực hiện bằng cách tạo đối tượng UITapGestureRecognizer (theo mặc định, đối tượng này sẽ phát hiện "cử chỉ" trên một lần nhấn để không cần tùy chỉnh thêm), chỉ định mục tiêu / hành động cho thời điểm cử chỉ được kích hoạt, sau đó gắn đối tượng nhận dạng cử chỉ vào chế độ xem bảng của bạn.

Ví dụ: Có lẽ trong viewDidLoadphương pháp của bạn :

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

hideKeyboardphương thức có thể trông như thế này:

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

Lưu ý rằng cử chỉ không được bắn ra khi chạm vào bên trong một UITextFieldvật thể. Nó được kích hoạt mặc dù trên UITableViewnền, chế độ xem chân trang, chế độ xem đầu trang và trên UILabelscác ô bên trong, v.v.


4
Khi tôi cố gắng này tôi thấy nó ngăn chặn bàn từ việc lựa chọn các tế bào :( tạo ảnh vui nhộn giải pháp khác.
Brian

109
Như một giải pháp dưới đây chỉ ra rằng bạn có thể làm cho công việc này tốt hơn nhiều bằng cách thiết lập:gestureRecognizer.cancelsTouchesInView = NO;
Zebs

3
Và đừng quên giải phóng cử chỉ sau khi nó được gắn vào tableView.
Paul Lynch

39
Đối với hideKeyboardphương pháp, thay vì giao tiếp trực tiếp với các trường văn bản, bạn có thể làm [self.view endEditing:NO];. Từ tài liệu của Apple: " Phương pháp này xem xét chế độ xem hiện tại và phân cấp chế độ xem phụ của nó cho trường văn bản hiện là người phản hồi đầu tiên. Nếu tìm thấy, nó sẽ yêu cầu trường văn bản đó từ chức làm người phản hồi đầu tiên. Nếu tham số force được đặt thành CÓ, trường văn bản thậm chí không bao giờ được hỏi; nó buộc phải từ chức. "
Gobot

1
bằng cách này, phương thức "didSelectRowAtIndexPath" của tôi không được gọi. bất kỳ giải pháp cho điều này?
uniruddh

127

Giải pháp UITapGestureRecognizer hoạt động với lựa chọn ô trong bảng nếu bạn đặt:

gestureRecognizer.cancelsTouchesInView = NO;

1
Điều này cho phép chạm vào tế bào, nhưng cử chỉ được công nhận là tốt, có lẽ chúng ta nên thực hiện điều này phương pháp đại biểushouldReceiveTouch
onmyway133

61

Đây là một cách tốt nhất để làm điều này. Chỉ cần làm điều này

[self.view endEditing:YES];

hoặc là

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

tôi nên đặt mã này ở đâu? xin lỗi tôi là người mới bắt đầu. Và vui lòng cung cấp mã nhanh.
John

54

Bạn cũng có thể làm điều đó từ Storyboard: nhập mô tả hình ảnh ở đây


1
Bất cứ điều gì tôi chọn: Loại bỏ khi kéo, Loại bỏ Tương tác, khi tôi chạm vào ô bảng, nó sẽ được chọn. Tôi đang sử dụng Xcode 8, swift 3. vui lòng giúp đỡ
John

22

Như UITableViewlà một lớp con của UIScrollView, việc triển khai một phương thức ủy nhiệm dưới đây cung cấp một giải pháp cực kỳ dễ dàng, nhanh chóng. Thậm chí không cần phải tham gia resignFirstResponderkể từ khi xem nội quan hệ thống phân cấp và tìm thấy người phản hồi hiện tại và yêu cầu nó từ chức trạng thái người trả lời của nó.

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

Và nhớ thêm UIScrollViewDelegatevào tệp tiêu đề.


2
Điều này có thể được thực hiện thông qua một lót này như ra nhọn bởi @Joe Masilotti nếu bạn đang nhắm mục tiêu iOS7 trở lên: self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
atulkhatri

Điều gì xảy ra nếu bạn nhấn vào một trường văn bản ở cuối màn hình được cho là cuộn lên để hiển thị bàn phím? - Bàn phím của bạn sẽ bị ẩn.
Islam Q.

Swift 4 - self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.onDrag
RobLabs

13

Trước hết, hãy lắng nghe scrollViewWillBeginDraggingcủa bạn UIViewControllerbằng cách thêm UIScrollViewDelegate:

Trong tệp .h:

@interface MyViewController : UIViewController <UIScrollViewDelegate> 

Trong tệp .m:

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

    [self dismissKeyboard];

}

Sau đó, lắng nghe các tương tác khác:

- (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];

}

Sau đó thực hiện dismissKeyboard:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    [yourTextFieldPointer resignFirstResponder];

}

Và nếu, giống như tôi, bạn muốn loại bỏ bàn phím cho một UITextField bên trong một ô bảng tùy chỉnh:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

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

}

Hy vọng rằng sẽ giúp bất cứ ai đang tìm kiếm !!



8

Đây là phiên bản nhanh chóng cho niềm vui viết mã của bạn:

Nó thêm một trình nhận dạng cử chỉ chạm sau đó loại bỏ bàn phím. Không cần đầu ra cho 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
Điều này hoạt động ngay cả với một tableViewCell tùy chỉnh! Tôi đã dành rất nhiều thời gian để cố gắng tìm ra điều này. Cảm ơn bạn rất nhiều! Bạn là người hùng của tôi. youtu.be/EqWRaAF6_WY
peacetype,

8

Có phiên bản Swift 3 không chặn vòi trên ô.

Trong viewDidLoad()phương pháp:

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

hideKeyboardtrông như thế này:

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

7

Tôi đã làm nó như thế này:

Tạo một phương thức trong TableViewController của bạn để hủy kích hoạt phản hồi đầu tiên (sẽ là TextBox của bạn tại thời điểm đó)

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

Khi tableView:didSelectRowAtIndexPath:gọi phương thức trước đó:

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

bạn đang làm sai theo cách bạn đang yêu cầu. bạn không đặt một nút trên giao diện bạn sẽ nói với quan điểm để loại bỏ các bàn phím giống như câu trả lời này nói

2
Điều này hoạt động tuyệt vời nếu bạn chạm vào bên trong ô xem bảng (và bên ngoài bất kỳ UITextField nào trong ô xem bảng đó). Tuy nhiên, nếu tôi chạm vào nền của chế độ xem bảng (thường là mục tiêu dễ lấy hơn - đúng là Định luật Fitts!), Thì không có may mắn như vậy. Đúng, đó là mong đợi, vì chúng tôi đang thực hiện thao tác này trong tableView: didSelectRowAtIndexPath :. Nếu điều này có thể được điều chỉnh bằng cách nào đó để hoạt động với việc chạm vào bất kỳ nơi nào khác trong chế độ xem bảng (nếu không sẽ không muốn lấy tiêu điểm bàn phím), tôi nghĩ chúng ta đã có người chiến thắng ở đây!
Joe D'Andrea

Tôi có cùng một vấn đề như jdandrea. Điều đó didSelectRowAtIndexPathkhông kích hoạt nếu bạn nhấn vào chính TableView.
zekel

nếu didSelectRowAtIndexPath không đủ, hãy thực hiện tương tự trong touchBegan!
Amogh Talpallikar

5

Tôi đã có UITableViewControllervà triển khai touchesBegan:withEvent:không hiệu quả với tôi.

Đây là những gì đã hoạt động:

Nhanh:

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

Mục tiêu-C:

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

Ý kiến ​​hay, tôi thích nó.
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

Sau đó, hãy đảm bảo rằng trong tệp Nib của bạn, bạn đã đặt loại UITableView của mình thành DismissableUITableView ..... có lẽ tôi đã nghĩ ra một cái tên tốt hơn cho lớp này, nhưng bạn hiểu được.


4

Nếu bạn đang nhắm mục tiêu iOS7, bạn có thể sử dụng một trong những cách sau:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

Cái trước sẽ tạo hoạt ảnh cho bàn phím ngoài màn hình khi màn hình xem bảng được cuộn và cái sau sẽ ẩn bàn phím giống như ứng dụng Tin nhắn có sẵn.

Lưu ý rằng đây là từ UIScrollView, UITableViewkế thừa từ.


đẹp. Tôi đã cố gắng giải quyết vấn đề bằng cách vuốt từ trên cao xuống màn hình cho đến khi bàn phím bắt đầu di chuyển xuống, sau đó vuốt ngược lên cho đến khi bàn phím di chuyển lên một chút rồi thả ra. chế độ xem cuộn không quay trở lại đầu như bình thường.
Sam

3

Thử cái này:

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 là một lớp con của UIScrollView.

Cách tôi đã làm là lắng nghe một sự kiện cuộn của người dùng và sau đó resignFirstResponder. Đây là phương thức UIScrollViewDelegate để triển khai trong mã của bạn;

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

Khi tiếp cận các loại vấn đề này, tôi thấy cách tốt nhất là nghiên cứu các giao thức ủy quyền cho từng đối tượng và các giao thức của các lớp cha (trong trường hợp này là UITableViewDelegate, UIScrollViewDelegate. Số lượng sự kiện đối tượng NS kích hoạt khá lớn và toàn diện. Đó là cũng dễ dàng hơn khi triển khai một giao thức sau đó phân lớp bất cứ thứ gì.


2

Tôi đã gặp vấn đề tương tự và đây là giải pháp của tôi, nó hoạt động hoàn hảo đối với tôi:

Trong chế độ xem hoặc bộ điều khiển chế độ xem mà bạn đã triển khai <UITextFieldDelegate>

(Trong trường hợp của tôi, tôi có một tùy chỉnh UITableViewCellđược gọi là TextFieldCell),

Khai báo UITapGestureRecognizernhư một thuộc tính:

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

Và khởi tạo nó trong chế độ xem / bộ điều khiển của bạn:

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

Trong - (void)textFieldDidBeginEditing:(UITextField *)textFieldphương thức này, hãy sử dụng superViewđể chuyển đến tableView của bạn và gọi addGestureRecognizer:

[self.superview.superview addGestureRecognizer:gestureRecognizer];

Và trong - (void)textFieldDidEndEditing:(UITextField *)textField, chỉ cần xóa trình nhận dạng cử chỉ:

[self.superview.superview removeGestureRecognizer:gestureRecognizer];

Hy vọng nó giúp.


Điều này đã làm điều đó cho tôi. Cảm ơn hac.jack
gilsaints88

2

Tôi muốn ô của mình mở bàn phím khi bất kỳ phần nào của ô được chọn và đóng nó nếu bạn nhấp vào bất kỳ vị trí nào ngoài ô. Để mở bàn phím:

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

(LƯU Ý: Tôi đã phân lớp con ô nhưng bạn có thể dễ dàng đạt được điều này trong tableView:didSelectRowAtIndexPath:phương thức ủy quyền của UITableView)

Làm điều này có nghĩa là với các giải pháp hàng đầu nếu bạn nhấp vào ô hai lần, bàn phím sẽ rung như vậy, trước tiên trình nhận dạng cử chỉ cố gắng đóng bàn phím và thứ hai, ô được chọn lại và thử mở bàn phím.

Giải pháp là kiểm tra xem nhấp chuột có xảy ra bên trong ô hiện được chọn hay không:

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

Tôi đã tìm thấy một giải pháp hoạt động tuyệt vời.

Cần thiết để sử dụng UIGestureRecognizerDelegate và phương thức - Cử chỉRecognizer: shouldReceiveTouch : .

Thêm trình nhận dạng cử chỉ vào TableView như sau:

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

Sau đó, triển khai phương thức ủy quyền shouldReceiveTouch để từ chối các thao tác chạm được thực hiện trong lớp UITableViewCell. Các hideKeyboard phương pháp duy nhất sẽ được gọi khi các liên lạc đã được thực hiện bên ngoài lớp 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

UITableViewcó một thuộc tính tiện dụng backgroundView, nhờ đó tôi đã đạt được hành vi này mà không gây rối với việc chọn ô, như được hiển thị bên dưới trong Swift:

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


1

Chỉ cần sử dụng UITapGestureRecognizer và cancelsTouchesInView = NOcó nghĩa là các thao tác nhấn vào ô và UITextViews cũng kích hoạt ẩn. Điều này thật tệ nếu bạn có nhiều UITextView và bạn nhấn vào cái tiếp theo. Bàn phím sẽ bắt đầu ẩn và sau đó textView tiếp theo trở thành Phản hồi đầu tiên và bàn phím sẽ hiển thị trở lại. Để tránh điều này, hãy kiểm tra vị trí nhấn và chỉ ẩn bàn phím nếu lần nhấn không nằm trên một ô:

// 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:được kích hoạt, thuộc tính của tableView scrollEnabledphải làYES

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

Hoàn hảo cho tôi. Đã thêm một hộp thư vào ô xem bảng; nếu tôi chạm vào bên ngoài bàn phím sa thải
Nicola

0

Tại sao bạn muốn tạo một bảng đầy các trường văn bản? Bạn nên sử dụng dạng xem chi tiết cho mỗi hàng chứa các trường văn bản. Khi bạn đẩy chế độ xem chi tiết của mình, hãy đảm bảo rằng bạn gọi "[myTextField trở thànhFirstResponder]" để người dùng có thể bắt đầu chỉnh sửa chỉ bằng một cú nhấp chuột từ danh sách bảng.


Ứng dụng Danh bạ của Apple thực hiện chính xác điều này. Tôi sẽ không nói rằng nó có đầy đủ các trường văn bản, nhưng nó sử dụng chúng để tạo hiệu quả tốt.
Joe D'Andrea

2
Chỉnh sửa nội dòng văn bản trong chế độ xem bảng nhanh hơn và trực quan hơn nhiều so với việc đẩy các chế độ xem chi tiết cho mọi trường văn bản mà người dùng muốn chỉnh sửa ... chỉ cần hỏi biểu mẫu HTML gần nhất của bạn hoặc các trường văn bản trong ngăn Tùy chọn iPhone hoặc ứng dụng Danh bạ, hoặc v.v ... vv ... thật tiếc là Apple đã không tạo ra loại ô tiêu chuẩn này, nhưng có nhiều thông tin trên web về việc đạt được điều này.
glenc

0

Nếu bạn sẵn sàng phân lớp (ugh!) Chế độ xem bảng của mình, một cái gì đó như thế này có thể hoạt động:

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

Nếu bạn muốn loại bỏ bàn phím trong khi nhấn phím quay lại, bạn chỉ cần thêm mã sau vào phương thức textField nên trả về, tức là:

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

Một số trường văn bản có thể có chế độ xem bộ chọn hoặc một số trường khác là chế độ xem phụ, vì vậy trong trường hợp đó, phương pháp trên không hoạt động, vì vậy trong trường hợp đó chúng ta cần sử dụng lớp UITapGestureRecognizer tức là thêm đoạn mã sau vào phương thức viewDidLoad, tức là:

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

    [self.view addGestureRecognizer:tap];

Bây giờ, chỉ cần thêm trình phản hồi từ chức vào phương thức bộ chọn, tức là:

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

Hy vọng nó sẽ giúp, cảm ơn :)


0

Nhiều câu trả lời thú vị. Tôi muốn biên dịch các cách tiếp cận khác nhau thành giải pháp mà tôi nghĩ phù hợp nhất với kịch bản UITableView (đó là kịch bản tôi thường sử dụng): Điều chúng tôi thường muốn về cơ bản là ẩn bàn phím trong hai trường hợp: khi chạm vào bên ngoài các phần tử Giao diện người dùng văn bản, hoặc khi cuộn xuống / lên UITableView. Kịch bản đầu tiên chúng ta có thể dễ dàng thêm thông qua TapGestureRecognizer và kịch bản thứ hai thông qua phương thức UIScrollViewDelegate scrollViewWillBeginDragging:. Đơn hàng đầu tiên của doanh nghiệp, phương pháp ẩn bàn phím:

   /**
     *  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];

    }

Phương pháp này từ chức bất kỳ giao diện người dùng textField nào của các chế độ xem phụ trong hệ thống phân cấp chế độ xem UITableView, vì vậy nó thực tế hơn là từ chức từng phần tử một cách độc lập.

Tiếp theo, chúng tôi xử lý loại bỏ thông qua cử chỉ Nhấn bên ngoài, với:

- (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];

}

Đặt tapGestureRecognizer.cancelsTouchesInView thành KHÔNG là để tránh cử chỉ ghi đè các hoạt động bình thường bên trong của UITableView (ví dụ: không can thiệp vào Lựa chọn ô).

Cuối cùng, để xử lý ẩn bàn phím trên Cuộn lên / xuống UITableView, chúng ta phải triển khai phương thức scrollViewWillBeginDragging: giao thức UIScrollViewDelegate, như:

tệp .h

@interface MyViewController : UIViewController <UIScrollViewDelegate>

tệp .m

#pragma mark - UIScrollViewDelegate

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

Tôi hy vọng nó sẽ giúp! =)


0

Đây là cách cuối cùng tôi đã thực hiện thành công. Tôi đã kết hợp các đề xuất và mã từ các câu trả lời khác nhau. Các tính năng: loại bỏ bàn phím, di chuyển các trường văn bản phía trên bàn phím trong khi chỉnh sửa và đặt kiểu trả lại bàn phím "Tiếp theo" và "Hoàn tất" .REPLACE "..." với nhiều trường hơn

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

Câu trả lời của @ mixca rất hữu ích nhưng nếu tôi có thứ gì đó khác với UITextField. Tôi nghĩ cách tốt nhất để xử lý nó bằng cách tìm kiếm tất cả các chế độ xem phụ của chế độ xem chính bằng hàm đệ quy, hãy kiểm tra ví dụ bên dưới

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

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

và bạn cũng có thể đưa phương thức này vào lớp tiện ích của mình và có thể sử dụng từ cử chỉ chạm như câu trả lời của @ mixca ..


0

Swift 4 / 4.2 / 5

Bạn cũng có thể loại bỏ bàn phím khi nhấn vào một ô - trước khi làm bất kỳ điều gì khác.

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.