Làm cách nào để loại bỏ bàn phím khi chỉnh sửa UITextField


181

Tôi biết rằng tôi cần nói với UITextField của mình từ chức phản hồi đầu tiên khi tôi muốn tháo bàn phím, nhưng tôi không biết làm thế nào để biết khi nào người dùng nhấn phím "Xong" trên bàn phím. Có một thông báo tôi có thể xem?


2
[self.view end Chỉnh sửa: CÓ]; liên lạc bắt đầu đại biểu là giải pháp tốt nhất
Zar E Ahmer

Câu trả lời:


351

Tôi đặt đại biểu của lớp UITextFieldtôi ViewController.

Trong lớp đó tôi đã thực hiện phương pháp này như sau:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return NO;
}

Xem ví dụ ở trên ... dây sử dụng IntefaceBuilder để thực hiện bất cứ điều gì bạn đang sử dụng làm bộ điều khiển của mình ... bất cứ khi nào người dùng bỏ qua hệ thống nhập văn bản (nhấn xong), điều này sẽ được gọi ...
Jason Coco

2
Một trong hai thứ này sẽ hoạt động - trường văn bản sẽ gửi hành động của nó khi người dùng nhấn phím Return ("Xong", bất cứ thứ gì) và cũng gửi đại biểu -textFieldShouldReturn :.

BTW - điều này cũng hoạt động cho một UISearchBar. Ví dụ: mã của tôi, tôi đã có một thành viên IBOutlet searchBarTusb; Khi 'phím trả về' (UIReturnKeySearch) của tôi được nhấp, - (void) searchBarSearchButtonClicky:, tôi đặt câu lệnh [searchBarTusb resignFirstResponder]; Cũng lưu ý, 'phím trả về' đã được đặt trong NIB bằng Trình tạo giao diện.
mobibob

Tại sao trở về NOthay vì YES?
Iulian Onofrei

@IulianOnofrei Hành vi mặc định của nút quay lại là thêm dòng trả về và giữ bàn phím trên màn hình. Bằng cách trả lại, NObạn tránh thêm một dòng trở lại văn bản.
kubi

47

Nếu bạn kết nối sự kiện DidEndOnExit của trường văn bản với một hành động (IBAction) trong InterfaceBuilder, nó sẽ bị rối khi người dùng bỏ bàn phím (bằng phím quay lại) và người gửi sẽ tham chiếu đến UITextField đã kích hoạt sự kiện.

Ví dụ:

-(IBAction)userDoneEnteringText:(id)sender
{
    UITextField theField = (UITextField*)sender;
    // do whatever you want with this text field
}

Sau đó, trong InterfaceBuilder, liên kết sự kiện DidEndOnExit của trường văn bản với hành động này trên bộ điều khiển của bạn (hoặc bất cứ điều gì bạn đang sử dụng để liên kết các sự kiện từ UI). Bất cứ khi nào người dùng nhập văn bản và loại bỏ trường văn bản, bộ điều khiển sẽ được gửi tin nhắn này.


Sự kiện duy nhất có vẻ như có thể hoạt động là textFieldDidEndEditing, trạng thái này chỉ được gửi sau khi UITextField từ bỏ trạng thái phản hồi đầu tiên. Làm thế nào để tôi biết khi nào tôi cần phải từ chức trạng thái phản hồi đầu tiên?
kubi

Tôi xin lỗi về thuật ngữ ... đây không phải là một thông báo thực tế (sự kiện) ... Tôi sẽ chỉnh sửa câu trả lời của mình bằng một ví dụ và giải thích nhanh, vì vậy hãy xem điều đó :)
Jason Coco

1
Để làm rõ câu trả lời này, textField sẽ gửi sự kiện "Đã kết thúc khi thoát" khi bạn nhấn phím quay lại, vì vậy đó là thứ bạn cần liên kết với bộ điều khiển của mình. Tôi nghĩ phương pháp này dễ hơn phương pháp tôi đã nêu ở trên.
kubi

2
bạn có thể chỉnh sửa câu trả lời này để nó đề cập đến sự kiện nào được nối dây không? Điều này rõ ràng là đẹp hơn so với thiết lập các đại biểu.
Dan Rosenstark

1
Muốn nâng cao câu trả lời này, nhưng không thể cho đến khi nó đề cập đến sự kiện DidEndOnExit. Ai đó có đặc quyền chỉnh sửa xin vui lòng thực hiện thay đổi nếu OP sẽ không?
James Hart

32

Bạn cũng có thể tạo một phương thức trong bộ điều khiển của bạn

 -(IBAction)editingEnded:(id)sender{
    [sender resignFirstResponder]; 
}

và sau đó trong Trình kiểm tra kết nối trong IB kết nối Sự kiện "Đã kết thúc khi thoát" với nó.


1
Điều này gần như không chính xác, hoặc ít nhất là nó bỏ lỡ điểm. Bằng cách đăng ký vào DidEndOnExitsự kiện, bạn không cần phải gọi resignFirstResponder. Bạn có thể kiểm tra điều này bằng cách đặt một điểm dừng tượng trưng [UIResponder resignFirstResponder]. Lưu ý rằng ngay cả khi bạn không gọi resignFirstResponder, hệ thống vẫn được gọi bởi hệ thống. Điều này được giải thích trong (các) cuốn sách xuất sắc của Matt Neuburg: apeth.com/iOSBook/ Kẻ
Chris Conover

19

kubi, cảm ơn Mã của bạn đã làm việc. Chỉ cần được rõ ràng (đối với người mới thích) như bạn nói, bạn phải thiết lập UITextField's delegatelà tương đương với ViewController trong đó cư trú trường văn bản. Bạn có thể làm điều này bất cứ nơi nào bạn muốn. Tôi đã chọn viewDidLoadphương pháp.

- (void)viewDidLoad 
{
    // sets the textField delegates to equal this viewController ... this allows for the keyboard to disappear after pressing done
    daTextField.delegate = self;
}

Nếu bạn đã thêm trường văn bản vào bảng phân cảnh hoặc NIB, bạn cũng có thể đặt trường văn bản delegateở đó. Bạn không cần phải làm điều này theo chương trình, như đã trình bày ở trên. Hoặc là cách tiếp cận hoạt động tốt.
Cướp

18

Đây là một mẹo để có được hành vi sa thải bàn phím tự động mà không có mã nào cả. Trong ngòi bút, chỉnh sửa đối tượng proxy Phản hồi đầu tiên trong Trình kiểm tra danh tính, thêm hành động phản hồi đầu tiên mới; chúng ta hãy gọi nó dummy:. Bây giờ hãy nối sự kiện Did End on Exit của trường văn bản vào dummy:hành động của đối tượng proxy Phản hồi đầu tiên. Đó là nó! Do sự kiện Did End on Exit của trường văn bản hiện có cặp mục tiêu hành động, nên trường văn bản sẽ tự động loại bỏ bàn phím của nó khi người dùng chạm trở lại; và vì không có hình phạt nào cho việc không tìm thấy trình xử lý cho một tin nhắn được gửi lên chuỗi phản hồi, ứng dụng không bị sập mặc dù không có triển khai ở dummy:bất cứ đâu.


@matt Tôi phát hiện ra rằng NẾU tôi thêm một segue thư giãn VÀ kết nối sự kiện didEndOnExit THÌ các segue thư giãn sẽ được kích hoạt khi nhấn Return. Không có kết nối sự kiện, segue không được kích hoạt. Tuyệt nhưng hả? Có nhận xét nào không? BTW: Tôi có sách Swift (đã hoàn thành) và iOS10 (trên chap 6) của bạn. Họ đã giúp tôi rất nhiều!
Verticon

@Verticon câu hỏi và câu trả lời không liên quan gì đến segues, vì vậy tôi không hiểu vấn đề này ... :( đây hoàn toàn là về việc sa thải bàn phím
matt

@matt Xin lỗi, anh bạn. Tôi đã ủng hộ vì 1) Tôi đã gặp chủ đề này trong khi tôi đang xử lý cách xử lý khóa trả về của UITextField; và 2) đó là cơ hội để tương tác với bạn (thx cho da sách). Không có "vấn đề". Tôi chỉ thiếu hiểu biết về lý do tại sao / cách thức hoạt động của nó.
Verticon

@Verticon Tôi xin lỗi vì không thể giúp đỡ. Vui lòng đặt câu hỏi mới với nhiều thông tin hơn (dự án demo?) Và đánh lừa tôi, nếu tôi có thể hữu ích.
matt


11

Chỉ cần thêm

[textField endEditing:YES];

nơi bạn muốn tắt bàn phím và hiển thị giao diện bộ chọn.


10

Trong Swift, bạn có thể viết IBAction trong Trình điều khiển và đặt sự kiện Đã kết thúc khi thoát của trường văn bản thành hành động đó

@IBAction func returnPressed(sender: UITextField) {
    self.view.endEditing(true)
}

5

Swift 4.2 và nó sẽ hoạt động 100%

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self

    }

    // hide key board when the user touches outside keyboard

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

    // user presses return key

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

4

Bạn cũng có thể dùng

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

   [self.yourTextField resignFirstResponder];

  }

Tốt nhất nếu bạn có nhiều Uitextfield:

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

2

Đây là những gì tôi phải làm để làm cho nó hoạt động và tôi nghĩ là cần thiết cho bất kỳ ai có Number Pad cho bàn phím (hoặc bất kỳ cái nào khác không có nút thực hiện:

  1. Tôi đã thay đổi UIView trong ViewContoder thành UIControl.
  2. Tôi đã tạo một hàm gọi là

    -(IBAction)backgroundIsTapped:(id)sender

Điều này cũng được định nghĩa trong tệp .h.

Sau này, tôi đã liên kết với bit 'chạm xuống' cho ViewContoder trong Trình tạo giao diện.

Trong chức năng 'nền được khai thác', tôi đặt điều này:

    [answerField resignFirstResponder];

Chỉ cần nhớ thay đổi 'answerField' thành tên của UITextField mà bạn muốn xóa bàn phím khỏi (rõ ràng là đảm bảo UITextField của bạn được xác định như bên dưới :)

    IBOutlet UITextField * <nameoftextfieldhere>;

Tôi biết chủ đề này có thể đã chết từ lâu ... nhưng tôi hy vọng điều này sẽ giúp được ai đó, ở đâu đó!


..nhưng nó không hoạt động tốt nếu người dùng chạm vào một điều khiển khác.
ragnarius

2

Bạn sẽ nhận thấy rằng phương thức "textFieldShouldReturn" cung cấp đối tượng trường văn bản đã nhấn phím DONE. Nếu bạn đặt TAG, bạn có thể bật trường văn bản đó. Hoặc bạn có thể theo dõi và so sánh con trỏ của đối tượng với một số giá trị thành viên được lưu bởi người tạo.

Cách tiếp cận của tôi là như thế này để tự học:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    bool fDidResign = [textField resignFirstResponder];

    NSLog(@"%s: did %resign the keyboard", __FUNCTION__, fDidResign ? @"" : @"not ");

    return fDidResign;
}

Trong khi đó, tôi đặt bài kiểm tra "xác nhận" từ chối việc từ chức sau đây. Nó chỉ mang tính minh họa, vì vậy nếu người dùng gõ KHÔNG! vào lĩnh vực này, nó sẽ không loại bỏ. Hành vi là như tôi muốn, nhưng trình tự đầu ra không như tôi mong đợi.

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    if( [[textField text] isEqualToString:@"NO!"] ) {
        NSLog(@"%@", textField.text);
        return NO;
    } else {
        return YES;
    }
}

Sau đây là đầu ra NSLog của tôi cho từ chối này theo sau là sự chấp nhận. Bạn sẽ nhận thấy rằng tôi đang trả lại kết quả của việc từ chức, nhưng tôi dự kiến ​​nó sẽ trả lại SAI cho tôi để báo cáo lại cho người gọi?! Ngoài ra, nó có hành vi cần thiết.

13.313 StudyKbd [109: 207] - [StudyKbdViewControll textFieldShouldReturn:]
13.320 StudyKbd [109: 207] - [StudyKbdViewControll textFieldShouldEndEditing:]
13.327 Nghiên cứuKbd [109: 207] KHÔNG!
13.333 StudyKbd [109: 207] - [StudyKbdViewControll textFieldShouldReturn:]: đã từ chức bàn phím
59.891 StudyKbd [109: 207] - [StudyKbdViewControll textFieldShouldReturn:]
59.897 StudyKbd [109: 207] - [StudyKbdViewControll textFieldShouldEndEditing:]
59.917 StudyKbd [109: 207] - [StudyKbdViewControll DoneEditText]: NO
59.928 StudyKbd [109: 207] - [StudyKbdViewControll textFieldShouldReturn:]: đã từ chức bàn phím

1
bạn có thể giải thích không .. nếu tôi trả về KHÔNG hoặc CÓ trong cả hai trường hợp điều tương tự xảy ra, vậy thì nhu cầu trả về có trong textFieldShouldReturn phương thức ủy nhiệm
K. Jaiswal

1

Dưới đây là một cách khá rõ ràng để kết thúc phiên bản với Phím Trả về hoặc chạm vào nền.

Trong Trình tạo giao diện, nhúng các trường của bạn vào chế độ xem lớp UIFormView

Lớp học này là gì:

  • Tự động đính kèm dưới dạng đại biểu trường (Được đánh thức từ ngòi hoặc được thêm thủ công)
  • Giữ một tài liệu tham khảo về lĩnh vực được chỉnh sửa hiện tại
  • Loại bỏ bàn phím khi quay lại hoặc chạm vào nền

Đây là mã:

Giao diện

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

-(BOOL)textFieldValueIsValid:(UITextField*)textField;
-(void)endEdit;

@end

Thực hiện

#import "UIFormView.h"

@implementation UIFormView
{
    UITextField* currentEditingTextField;
}

// Automatically register fields

-(void)addSubview:(UIView *)view
{
    [super addSubview:view];
    if ([view isKindOfClass:[UITextField class]]) {
        if ( ![(UITextField*)view delegate] ) [(UITextField*)view setDelegate:self];
    }
}

// UITextField Protocol

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    currentEditingTextField = textField;
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    currentEditingTextField = NULL;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self endEdit];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if ([self textFieldValueIsValid:textField]) {
        [self endEdit];
        return YES;
    } else {
        return NO;
    }
}

// Own functions

-(void)endEdit
{
    if (currentEditingTextField) {
        [currentEditingTextField endEditing:YES];
        currentEditingTextField = NULL;
    }
}


// Override this in your subclass to handle eventual values that may prevent validation.

-(BOOL)textFieldValueIsValid:(UITextField*)textField
{
    return YES;
}

@end
  • Bằng cách phân lớp biểu mẫu và ghi đè textFieldValueIsValid:phương thức, bạn có thể tránh kết thúc phiên bản nếu giá trị không chính xác cho trường đã cho.

  • Nếu một trường có một đại biểu được đặt trong Trình tạo giao diện, thì biểu mẫu không thay đổi nó. Tôi không thấy nhiều lý do để đặt một đại biểu khác cho một lĩnh vực cụ thể, nhưng tại sao lại không

Có nhiều cách để cải thiện lớp dạng xem biểu mẫu này - Đính kèm một đại biểu, thực hiện một số bố cục, xử lý khi bàn phím bao phủ một trường (sử dụng khung currentEditingTextField), tự động bắt đầu phiên bản cho trường tiếp theo, ...

Cá nhân tôi giữ nó trong khuôn khổ của mình và luôn phân lớp nó để thêm các tính năng, nó thường khá hữu ích "như hiện tại".

Tôi hy vọng nó sẽ giúp. Chúc mừng tất cả


1
Lớp học hữu ích. Một điểm nhỏ, bạn không nên đặt tiền tố cho các lớp của riêng mình bằng "UI". Trong object-c, bạn nên sử dụng tiền tố của riêng bạn ("TL"?), Trong Swift, không sử dụng bất cứ thứ gì.
kubi

Cảm ơn @kubi. Đúng rồi. Đó là MF trong khuôn khổ của tôi, như MooseFactory;)
Moose

1

nếu bạn muốn tất cả chỉnh sửa trong UIViewControll bạn có thể sử dụng.

[[self view]endEditing:YES];

và nếu bạn muốn loại bỏ ẩn bàn phím UITextField vuông góc thì hãy sử dụng.

1.add ủy nhiệm trong viewcontroll.h của bạn

<UITextFieldDelegate>
  1. làm cho phái đoàn không thể đến trường văn bản của bạn.

    self.yourTextField.delegate = tự;

  2. thêm phương thức này vào trình điều khiển khung nhìn của bạn.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; trả về CÓ;}


1

Lập trình đặt đại biểu của UITextField trong swift 3

Triển khai UITextFieldDelegate trong tệp ViewContoder.Swift của bạn (ví dụ: lớp ViewContoder: UIViewContoder, UITextFieldDelegate {)

 lazy var firstNameTF: UITextField = {

    let firstname = UITextField()
    firstname.placeholder = "FirstName"
    firstname.frame = CGRect(x:38, y: 100, width: 244, height: 30)
    firstname.textAlignment = .center
    firstname.borderStyle = UITextBorderStyle.roundedRect
    firstname.keyboardType = UIKeyboardType.default
    firstname.delegate = self
    return firstname
}()

lazy var lastNameTF: UITextField = {

    let lastname = UITextField()
    lastname.placeholder = "LastName"
    lastname.frame = CGRect(x:38, y: 150, width: 244, height: 30)
    lastname.textAlignment = .center
    lastname.borderStyle = UITextBorderStyle.roundedRect
    lastname.keyboardType = UIKeyboardType.default
    lastname.delegate = self
    return lastname
}()

lazy var emailIdTF: UITextField = {

    let emailid = UITextField()
    emailid.placeholder = "EmailId"
    emailid.frame = CGRect(x:38, y: 200, width: 244, height: 30)
    emailid.textAlignment = .center
    emailid.borderStyle = UITextBorderStyle.roundedRect
    emailid.keyboardType = UIKeyboardType.default
    emailid.delegate = self
    return emailid
}()

// Đánh dấu: - xử lý văn bản ủy nhiệm ..

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    if textField == firstNameTF {

        lastNameTF.becomeFirstResponder()
    }

    else if textField == lastNameTF {

        emailIdTF.becomeFirstResponder()
    }
    else {
        view.emailIdTF(true)
    }
    return true
}

0

Tạo một bảng ẩn chức năng và liên kết nó với trường văn bản trong tệp .xib và chọn DidEndOnExit

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  

0

Nếu bạn đã tạo chế độ xem bằng Trình tạo giao diện, hãy sử dụng cách sau Chỉ cần tạo phương thức,

-(IBAction)dismissKeyboard:(id)sender
{
[sender resignFirstResponder];
}

Chỉ cần nhấp chuột phải vào trường văn bản trong dạng xem và đặt sự kiện là Đã kết thúc khi thoát và nối nó với phương thức "từ chối".

Hướng dẫn tốt nhất cho người mới bắt đầu là "Phát triển iPhone và iPad đầu tiên, Phiên bản 2"


0

thử cái này

- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    return YES;
}

0
//====================================================
//                  textFieldShouldReturn:
//====================================================
-(BOOL) textFieldShouldReturn:(UITextField*) textField { 
    [textField resignFirstResponder];
    if(textField.returnKeyType != UIReturnKeyDone){
        [[textField.superview viewWithTag: self.nextTextField] becomeFirstResponder];
    }
    return YES;
}

0

Bất cứ ai đang tìm kiếm Swift 3

1) Đảm bảo rằng Đại biểu UITextField của bạn được kết nối với ViewContoder của bạn trong Storyboard

2) Triển khai UITextFieldDelegate trong tệp ViewContoder.Swift của bạn (ví dụ: lớp ViewContoder: UIViewControll, UITextFieldDelegate {)

3) Sử dụng phương pháp đại biểu dưới đây

func textFieldShouldReturn(textField: UITextField) -> Bool { 
   textField.resignFirstResponder()  
return false }

0

Đây là cách tôi loại bỏ bàn phím trong Swift 4.2 và nó hoạt động với tôi:

    override func viewDidLoad() {
    super.viewDidLoad()

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

    view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    numberField.resignFirstResponder()
    }

-2

Swift 3, iOS 9+

@IBAction private func noteFieldDidEndOnExit(_ sender: UITextField) {}

CẬP NHẬT: Nó vẫn hoạt động tốt cho tôi. Tôi nghĩ rằng anh chàng dành câu trả lời này chỉ không hiểu rằng anh ta cần phải ràng buộc hành động này với UITextField tại bảng phân cảnh.


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.