Làm cách nào để loại bỏ bàn phím cho UITextView bằng phím quay lại?


382

Trong thư viện của IB, phần giới thiệu cho chúng ta biết rằng khi returnnhấn phím, bàn phím UITextViewsẽ biến mất. Nhưng trên thực tế, returnkhóa chỉ có thể hoạt động như '\ n'.

Tôi có thể thêm một nút và sử dụng [txtView resignFirstResponder]để ẩn bàn phím.

Nhưng có cách nào để thêm hành động cho returnphím trong bàn phím để tôi không cần thêm UIButtonkhông?


Làm theo hướng dẫn trên bài viết trên blog này: iphonedevelopertips.com/cocoa/...
ManojN

Câu trả lời:


354

UITextViewkhông có bất kỳ phương thức nào sẽ được gọi khi người dùng nhấn phím quay lại. Nếu bạn muốn người dùng chỉ có thể thêm một dòng văn bản, hãy sử dụng a UITextField. Nhấn trở lại và ẩn bàn phím UITextViewkhông tuân theo các nguyên tắc giao diện.

Ngay cả sau đó nếu bạn muốn làm điều này, hãy thực hiện textView:shouldChangeTextInRange:replacementText:phương pháp UITextViewDelegatevà trong đó kiểm tra xem văn bản thay thế là \n, ẩn bàn phím.

Có thể có những cách khác nhưng tôi không biết về bất kỳ.


1
Cảm ơn và phương pháp hoạt động tốt. Lý do để sử dụng UITextView là nó có thể chứa văn bản trong nhiều dòng. Và bây giờ tôi đang sử dụng nó như một hộp tin nhắn.
Chilly Zhong

28
Thật dễ dàng để thay đổi phím quay lại thành "đã hoàn thành" bằng cách sử dụng [textField setReturnKeyType: UIReturnKeyDone];hoặc sử dụng trình tạo giao diện
Casebash

9
Được rồi, bây giờ tôi hiểu rằng cách hoàn thiện của Apple với trường văn bản nhiều dòng là thêm được thực hiện vào thanh menu
Casebash

8
Đây không phải là một cách tốt để giải quyết vấn đề này vì bạn đang hạn chế người dùng sử dụng enter để đi ra khỏi bàn phím. Có lẽ cách tốt nhất là thêm một nút thực thi phương thức resignFirstResponder.
Mười một

5
@Casebash. Có vẻ như việc đặt phím quay lại thành "đã hoàn thành" không giải quyết được vấn đề trong Xcode 6.4, Swift 2.0. Tôi đặt khóa bằng IB.
MB_iOS Nhà phát triển

505

Hình tôi sẽ đăng đoạn trích ngay tại đây:

Hãy chắc chắn rằng bạn tuyên bố hỗ trợ cho UITextViewDelegategiao thức.

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

    if([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }

    return YES;
}

Cập nhật Swift 4.0:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
        return false
    }
    return true
}

75
Vấn đề là đây không thực sự là một cách phát hiện người dùng đã gõ phím quay lại . Người dùng có thể dán ký tự trả về vào trường văn bản và bạn sẽ nhận được thông báo đại biểu tương tự. Về cơ bản bạn đang sử dụng sai chế độ xem văn bản. Cách để tắt bàn phím là (1) hoàn toàn không làm như vậy (như khi soạn thư trong ứng dụng Thư) hoặc (2) để có nút Xong ở nơi khác trong giao diện (như trong ứng dụng Ghi chú). Bạn có thể đính kèm một nút như một chế độ xem phụ kiện vào bàn phím chẳng hạn.
matt

@ Sam V mà đoạn trích là người đàn ông tuyệt vời. nó làm việc cho tôi cảm ơn một người đàn ông tấn. Có bất kỳ đoạn trích cho bàn phím số. liên quan đến shishir
shishir

Lộng lẫy. Chỉ cần một lời nhắc nhở rằng trong một số tình huống, để thoát khỏi bàn phím, hãy thử dọc theo dòng ... [self.view endEditing: YES];
Fattie

@Vojto, hoạt động tốt trên iPad. Bạn có thể chưa đặt đại biểu.
Vincent

4
Vấn đề là bàn phím có thể bị ẩn một phần của giao diện được sử dụng để loại bỏ. Điều thực sự vô lý là IOS không có nút trên mỗi bàn phím dành riêng để loại bỏ bàn phím để người dùng có thể làm như vậy nếu muốn.
Sani Elfishawy

80

Tôi biết điều này đã được trả lời nhưng tôi thực sự không thích sử dụng chuỗi ký tự cho dòng mới vì vậy đây là những gì tôi đã làm.

- (BOOL)textView:(UITextView *)txtView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if( [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location == NSNotFound ) {
        return YES;
    }

    [txtView resignFirstResponder];
    return NO;
}

Cập nhật Swift 4.0:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text as NSString).rangeOfCharacter(from: CharacterSet.newlines).location == NSNotFound {
    return true
}
txtView.resignFirstResponder()
return false
}

6
Tôi có thể sửa đổi nó như thế này: NSRange resultRange = [text RangeOfCharacterFromset: [NSCharacterSet newlineCharacterSet] tùy chọn: NSBackwardsSearch]; Vì dù sao đây cũng là một bản hack, nên có vẻ như việc kiểm tra phần cuối của chuỗi để trả lại có thể là con đường an toàn hơn.
maxpower

@maxpower Nhận xét rất tốt. Ngoài ra, tốt hơn là kiểm tra văn bản thay thế, ví dụ NSString *replacedText = [textView.text stringByReplacingCharactersInRange:range withString:text].
Rudolf Adamkovič

Hãy tưởng tượng người dùng dán một số văn bản được sao chép từ nơi khác có chứa một dòng mới. Họ có thể sẽ bối rối khi thay vì nối thêm văn bản, ứng dụng chỉ tắt bàn phím.
Nikolai Ruhe

44

Tôi biết điều này đã được trả lời rất nhiều lần, nhưng đây là hai xu của tôi cho vấn đề này.

Tôi tìm thấy câu trả lời bằng samvermetteribeto thực sự hữu ích, và cũng có những nhận xét của maxpower trong ribeto câu trả lời 's. Nhưng có một vấn đề với những cách tiếp cận đó. Vấn đề mà mờ đề cập trong samvermette 's câu trả lời và nó rằng nếu người dùng muốn dán cái gì đó với một ngắt dòng bên trong nó, bàn phím sẽ che giấu mà không dán bất cứ điều gì.

Vì vậy, cách tiếp cận của tôi là hỗn hợp của ba giải pháp được đề cập ở trên và chỉ kiểm tra xem chuỗi đã nhập có phải là một dòng mới hay không khi độ dài của chuỗi là 1 vì vậy chúng tôi đảm bảo người dùng đang gõ thay vì dán.

Đây là những gì tôi đã làm:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    NSRange resultRange = [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch];
    if ([text length] == 1 && resultRange.location != NSNotFound) {
        [textView resignFirstResponder];
        return NO;
    }

    return YES;
}

Đây là một giải pháp tốt nhất cho vấn đề này. câu trả lời lấy mẫu không giải thích tình huống người dùng muốn dán văn bản.
marcopaivaf

36

Một cách thanh lịch hơn là loại bỏ bàn phím khi người dùng chạm vào một nơi nào đó bên ngoài khung của bàn phím.

Đầu tiên, đặt chế độ xem ViewContoder của bạn thành lớp "UIControl" trong trình kiểm tra danh tính trong UIBuilder. Điều khiển kéo chế độ xem vào tệp tiêu đề của ViewContoder và liên kết nó dưới dạng một hành động với sự kiện như Touch Up Inside, chẳng hạn như:

ViewControll.h

-(IBAction)dismissKeyboardOnTap:(id)sender;

Trong tệp ViewContoder chính, ViewControll.m:

-(IBAction)dismissKeyboardOnTap:(id)sender
    {
         [[self view] endEditing:YES];
    }

Bạn có thể yêu cầu chạm hai lần hoặc chạm dài bằng các kỹ thuật tương tự. Bạn có thể cần đặt ViewContoder của mình thành UITextViewDelegate và kết nối TextView với ViewContoder. Phương pháp này hoạt động cho cả UITextView và UITextField.

Nguồn: Nông trại Big Nerd

EDIT: Tôi cũng muốn thêm rằng nếu bạn đang sử dụng UIScrollView, kỹ thuật trên có thể không hoạt động dễ dàng thông qua Trình tạo giao diện. Trong trường hợp đó, bạn có thể sử dụng UIGestureRecognizer và gọi phương thức [[self view] endEditing: YES] trong đó. Một ví dụ sẽ là:

-(void)ViewDidLoad{
    ....
    UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc] 
        initWithTarget:self action:@selector(tap:)];
    [self.view addGestureRecognizer: tapRec];
    ....
}

-(void)tap:(UITapGestureRecognizer *)tapRec{
    [[self view] endEditing: YES];
}

Khi người dùng gõ bên ngoài bàn phím và không nhấn vào không gian nhập, bàn phím sẽ tắt.


1
Tôi thích ý tưởng với GestureRecognizernhưng vấn đề lớn là tất cả các nút hoặc điều khiển trên chế độ xem không còn có thể nhấp được.
chuyên gia

35

Thêm phương pháp này trong trình điều khiển xem của bạn.

Swift :

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
        return false
    }
    return true
}

Phương pháp này cũng có thể hữu ích cho bạn:

/**
Dismiss keyboard when tapped outside the keyboard or textView

:param: touches the touches
:param: event   the related event
*/
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    if let touch = touches.anyObject() as? UITouch {
        if touch.phase == UITouchPhase.Began {
            textField?.resignFirstResponder()
        }
    }
}

2
Đừng quên xác nhận giao thức UITextViewDelegate :)
swiftBoy

Tôi không nghĩ rằng đó là một ý tưởng tốt để ghi đè lên TouchBegan và không gọi super.touchesBegan(touches:withEvent:).
TGO

Để thể hiện bản chất đối xứng của mã này, bạn nên viết else { return true }.
ý nghĩa-vấn đề

@ ý nghĩa-vấn đề hoàn toàn không
Alexander Volkov

@AlexanderVolkov Bạn không đồng ý rằng đó là một tình huống đối xứng, bạn không biết ý tôi là gì, bạn không tin vào giá trị của mã chính xác về ngữ nghĩa, hay, ...?
ý nghĩa-vấn đề

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

yourtextView.delegate=self;

Cũng thêm UITextViewDelegate

Đừng quên xác nhận giao thức

NẾU bạn không thêm if([text isEqualToString:@"\n"])bạn không thể chỉnh sửa


2
-1 Đây chỉ là một phiên bản nghèo hơn của câu trả lời của samvermette. Bạn đã bỏ lỡ trở lại NOnếu văn bản bằng @"\n".
devios1

17

Có một giải pháp khác trong khi sử dụng với uitextview, Bạn có thể thêm thanh công cụ là InputAccessoryView trong "textViewShouldBeginEditing" và từ nút thực hiện của thanh công cụ này, bạn có thể bỏ qua bàn phím, mã này là như sau:

Trong viewDidLoad

toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)]; //toolbar is uitoolbar object
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(btnClickedDone:)];
[toolBar setItems:[NSArray arrayWithObject:btnDone]];

Trong phương pháp textviewdelegate

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
     [textView setInputAccessoryView:toolBar];
     return YES;
}

Trong hành động của Nút Xong trong thanh công cụ là như sau:

-(IBAction)btnClickedDone:(id)sender
{
    [self.view endEditing:YES];
}

17

Tôi tìm thấy câu trả lời của josebama là câu trả lời đầy đủ và rõ ràng nhất có sẵn trong chủ đề này.

Dưới đây là cú pháp Swift 4 cho nó:

func textView(_ textView: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
    let resultRange = text.rangeOfCharacter(from: CharacterSet.newlines, options: .backwards)
    if text.count == 1 && resultRange != nil {
        textView.resignFirstResponder()
        // Do any additional stuff here
        return false
    }
    return true
}

Các resultRangemục tiêu để kiểm tra xem các văn bản chỉ chứa ký tự dòng mới mà tránh được mã hóa cứng "\ n".
Thanh Hoa

6

nhanh

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
    }
    return true
}

và cấu hình


Màn hình đó được chụp từ đâu?
Sam

6

Sử dụng bộ điều khiển điều hướng để lưu trữ một thanh để loại bỏ bàn phím:

trong tệp .h:

UIBarButtonItem* dismissKeyboardButton;

trong tệp .m:

- (void)viewDidLoad {
    dismissKeyboardButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissKeyboard)];
}

-(void)textViewDidBeginEditing:(UITextView *)textView {
    self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField {
    self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}

-(void)dismissKeyboard {
    [self.textField resignFirstResponder];
    [self.textView resignFirstResponder];
    //or replace this with your regular right button
    self.navigationItem.rightBarButtonItem = nil;
}

5

Giống như nhận xét mờ cho samvermette, tôi cũng không thích ý tưởng phát hiện "\ n". Khóa "return" có một lý do trong UITextView, đó là đi đến dòng tiếp theo của khóa học.

Theo tôi, giải pháp tốt nhất là bắt chước ứng dụng tin nhắn iPhone - đó là thêm thanh công cụ (và nút) trên bàn phím.

Tôi đã nhận được mã từ bài viết sau blog:

http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/

Các bước:

-Thêm thanh công cụ vào tệp XIB của bạn - đặt chiều cao thành 460

-Thêm mục nút thanh công cụ (nếu chưa được thêm). Nếu bạn cần căn chỉnh đúng, cũng thêm mục nút thanh linh hoạt vào XIB và di chuyển mục nút thanh công cụ

-Tạo hành động liên kết mục nút của bạn để từ chứcFirstResponder như sau:

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

-Sau đó:

- (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 {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];

    CGRect frame = self.keyboardToolbar.frame;
    frame.origin.y = self.view.frame.size.height - 260.0;
    self.keyboardToolbar.frame = frame;

    [UIView commitAnimations];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];

    CGRect frame = self.keyboardToolbar.frame;
    frame.origin.y = self.view.frame.size.height;
    self.keyboardToolbar.frame = frame;

    [UIView commitAnimations];
}

Đề ra. Mặc dù giải pháp của bạn rất thanh lịch, nhưng nó không trả lời cho câu hỏi ban đầu: "Làm cách nào để loại bỏ bàn phím cho UITextView bằng phím quay lại?". Có những tình huống khi UITextView được sử dụng để mô phỏng một từ UITextField, không nhập nhiều dòng.
SwiftArchitect

2
Mặc dù nó lạc đề, nhưng nó rất hữu ích. Tôi cũng muốn một UITextView được nhập bằng nhiều dòng và loại bỏ bàn phím khi tôi muốn.
Yeung

5

Chỉ cần giải quyết vấn đề này một cách khác.

  • Tạo một nút sẽ được đặt trong nền
  • Từ Trình kiểm tra thuộc tính, thay đổi loại nút thành tùy chỉnh và làm cho nút trong suốt.
  • Mở rộng nút để bao quát toàn bộ chế độ xem và đảm bảo nút nằm phía sau tất cả các đối tượng khác. Cách dễ dàng để làm điều này là kéo nút lên trên cùng của chế độ xem danh sách trong Chế độ xem
  • Điều khiển kéo nút vào viewController.htệp và tạo hành động (Sự kiện đã gửi: Chạm vào bên trong) như:

    (IBAction)ExitKeyboard:(id)sender;
  • Trong ViewController.mnên trông như:

    (IBAction)ExitKeyboard:(id)sender {
        [self.view endEditing:TRUE];
    }
  • Chạy ứng dụng và khi bạn nhấp vào khỏi TextView, bàn phím sẽ biến mất

Bạn cũng phải thêm: - (void) textViewDidEndEditing: (UITextView *) textView {[self.TextView resignFirstResponder]; }
samouray

5

Thêm một người quan sát trong viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];

và sau đó sử dụng bộ chọn để kiểm tra "\ n"

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

  if ([[[notification object] text] hasSuffix:@"\n"])
  {
    [[notification object] resignFirstResponder];
  }
}

Nó không sử dụng "\ n" và không kiểm tra cụ thể khóa trả về, nhưng tôi nghĩ điều này là ổn.

CẬP NHẬT

Xem câu trả lời của ribto dưới đây sử dụng [NSCharacterSet newlineCharacterSet]thay cho\n


Err nó không sử dụng \nvà trả về khóa được phát hiện dựa trên \nđể nó kiểm tra khóa trả về. Sự khác biệt duy nhất là bạn đang sử dụng thông báo thay vì sử dụng textViewDelegates.
GoodSp33d

Bây giờ tôi nghĩ rằng kiểm tra [NSCharacterSet newlineCharacterSet]thay vì \ n có thể là một cách tốt hơn để đi.
ToddB

5

Mã Swift

Triển khai UITextViewDelegate trong lớp của bạn / Xem như vậy:

class MyClass: UITextViewDelegate  { ...

đặt đại biểu textView thành tự

myTextView.delegate = self

Và sau đó thực hiện như sau:

  func textViewDidChange(_ textView: UITextView) {
    if textView.text.characters.count >= 1 {

        if let lastChar = textView.text.characters.last {

            if(lastChar == "\n"){

              textView.text = textView.text.substring(to: textView.text.index(before: textView.text.endIndex))
              textView.resignFirstResponder()
            }
        }
    }
}

EDIT Tôi đã cập nhật mã bởi vì không bao giờ nên thay đổi đầu vào của người dùng trong trường văn bản thành một cách giải quyết và không đặt lại trạng thái sau khi mã hack hoàn thành.


4

Thử cái này :

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if ([text isEqualToString:@"\n"]) {
        [self.view endEditing:YES];
    }

    return YES;

}

4

// Bạn có thể sử dụng ...

Bước 1. Bước đầu tiên là đảm bảo rằng bạn khai báo hỗ trợ cho UITextViewDelegategiao thức. Điều này được thực hiện trong tệp tiêu đề của bạn, ví dụ ở đây là tiêu đề được gọi là

EditorControll.h:

@interface EditorController : UIViewController  {
  UITextView *messageTextView;
}

@property (nonatomic, retain) UITextView *messageTextView;

@end

Bước 2. Tiếp theo, bạn sẽ cần phải đăng ký bộ điều khiển với tư cách là đại biểu của UITextView. Tiếp tục từ ví dụ trên, đây là cách tôi khởi tạo UITextViewvới EditorControllertư cách là đại biểu

- (id) init {
    if (self = [super init]) {
        // define the area and location for the UITextView
        CGRect tfFrame = CGRectMake(10, 10, 300, 100);
        messageTextView = [[UITextView alloc] initWithFrame:tfFrame];
        // make sure that it is editable
        messageTextView.editable = YES;

        // add the controller as the delegate
        messageTextView.delegate = self;
    }

Bước 3. Và bây giờ, mảnh ghép cuối cùng là thực hiện hành động để đáp lại shouldCahngeTextInRangethông điệp như sau:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range 
  replacementText:(NSString *)text
{
    // Any new character added is passed in as the "text" parameter
    if ([text isEqualToString:@"\n"]) {
        // Be sure to test for equality using the "isEqualToString" message
        [textView resignFirstResponder];

        // Return FALSE so that the final '\n' character doesn't get added
        return FALSE;
    }
    // For any other character return TRUE so that the text gets added to the view
    return TRUE;
}

3

Bạn cũng có thể ẩn bàn phím khi chạm vào màn hình xem:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch * touch = [touches anyObject];
     if(touch.phase == UITouchPhaseBegan) {
        [txtDetail resignFirstResponder];
      }
 }

IMHO, đây là cách tiếp cận rất tốt, tốt hơn nhiều so với nút bao trùm toàn bộ chế độ xem.
WebOrCode

3

Trả lời nhanh:

override func viewDidLoad() {
    super.viewDidLoad()
    let tapGestureReconizer = UITapGestureRecognizer(target: self, action: "tap:")
    view.addGestureRecognizer(tapGestureReconizer)
}

func tap(sender: UITapGestureRecognizer) {
    view.endEditing(true)
}

3

Tôi đã sử dụng mã này để thay đổi phản hồi.

 - (BOOL)textView:(UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
    {
        if ([text isEqualToString:@"\n"]) {
            //[textView resignFirstResponder];
            //return YES;
            NSInteger nextTag = textView.tag + 1;
            // Try to find next responder
            UIResponder* nextResponder = [self.view viewWithTag:nextTag];
            if (nextResponder) {
                // Found next responder, so set it.
                [nextResponder becomeFirstResponder];
            } else {
                // Not found, so remove keyboard.
                [textView resignFirstResponder];
            }
            return NO; 


            return NO;
        }
        return YES;

    }

tại sao không sử dụng [self.view endEditing: CÓ]; Một lần??
ajay_nasa

3

Câu hỏi hỏi làm thế nào để làm điều đó với phím quay lại nhưng tôi nghĩ rằng điều này có thể giúp ai đó có ý định làm cho bàn phím biến mất khi sử dụng UITextView:

private func addToolBarForTextView() {
    let textViewToolbar: UIToolbar = UIToolbar()
    textViewToolbar.barStyle = .default
    textViewToolbar.items = [
        UIBarButtonItem(title: "Cancel", style: .done,
                  target: self, action: #selector(cancelInput)),
        UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
                  target: self, action: nil),
        UIBarButtonItem(title: "Post Reply", style: .done,
                  target: self, action: #selector(doneInput))
    ]
    textViewToolbar.sizeToFit()
    yourTextView.inputAccessoryView = textViewToolbar
}

@objc func cancelInput() { print("cancel") }
@objc func doneInput() { print("done") }

override func viewDidLoad() {
    super.viewDidLoad()
    addToolBarForTextView()
}

Gọi addToolBarForTextView () trong viewDidLoad hoặc một số phương thức vòng đời khác.

Dường như đó là giải pháp hoàn hảo cho tôi.

Chúc mừng

Murat


1
Cho năm 2019 bây giờ sao chép và dán, không có lỗi cú pháp và đặt tên hiện tại
Fattie

1
cho đến nay câu trả lời tốt nhất ở đây. Tôi chỉ sửa lỗi cú pháp đơn giản, tất nhiên chỉnh sửa theo ý muốn. Cảm ơn!
Fattie

2

Đồng ý. Mọi người đã đưa ra câu trả lời bằng các thủ thuật nhưng tôi nghĩ cách đúng đắn để đạt được điều này là bằng cách

Kết nối hành động sau với sự kiện " Đã kết thúc khi thoát " Interface Builder. (nhấp chuột phải vào TextFieldvà kéo cntrl từ ' Đã kết thúc khi thoát ' sang phương thức sau.

-(IBAction)hideTheKeyboard:(id)sender
{
    [self.view endEditing:TRUE];
}

6
-1 Câu hỏi là về UITextView chứ không phải UITextField bạn của tôi
Yogi

2
hầu hết các câu trả lời đều có ở đây với phiếu bầu vì nó phù hợp với nhiều kịch bản khác nhau của nhà phát triển khác nhau.
carbonr

Nếu bạn đang sử dụng UITextField, đây là cách để làm điều đó. BTW, bạn nên sử dụng CÓ / KHÔNG cho BOOL khách quan-C, không phải TRUE / FALSE.
Jon Shier

1
@jshier: TRUE / FALSE cũng OK
Yogi

2

Tương tự các câu trả lời khác bằng cách sử dụng UITextViewDelegatenhưng giao diện nhanh hơn mới hơn isNewlinesẽ là:

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if let character = text.first, character.isNewline {
        textView.resignFirstResponder()
        return false
    }
    return true
}

1
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range  replacementText:(NSString *)text
{
    if (range.length==0) {
        if ([text isEqualToString:@"\n"]) {
            [txtView resignFirstResponder];
            if(textView.returnKeyType== UIReturnKeyGo){

                [self PreviewLatter];
                return NO;
            }
            return NO;
        }
    }   return YES;
}

1
+ (void)addDoneButtonToControl:(id)txtFieldOrTextView
{
    if([txtFieldOrTextView isKindOfClass:[UITextField class]])
    {
        txtFieldOrTextView = (UITextField *)txtFieldOrTextView;
    }
    else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
    {
        txtFieldOrTextView = (UITextView *)txtFieldOrTextView;
    }

    UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0,
                                                                          0,
                                                                          [Global returnDeviceWidth],
                                                                          50)];
    numberToolbar.barStyle = UIBarStyleDefault;


    UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"btn_return"]
                                                                style:UIBarButtonItemStyleBordered
                                                               target:txtFieldOrTextView
                                                               action:@selector(resignFirstResponder)];

    numberToolbar.items = [NSArray arrayWithObjects:btnDone,nil];
    [numberToolbar sizeToFit];

    if([txtFieldOrTextView isKindOfClass:[UITextField class]])
    {
         ((UITextField *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
    }
    else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
    {
         ((UITextView *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
    }
}

0

Tôi biết đó không phải là câu trả lời chính xác cho câu hỏi này, nhưng tôi đã tìm thấy chủ đề này sau khi tìm kiếm trên internet để tìm câu trả lời. Tôi giả sử người khác chia sẻ cảm giác đó.

Đây là phương sai của tôi về UITapGestureRecognizer mà tôi thấy đáng tin cậy và dễ sử dụng - chỉ cần đặt đại biểu của TextView thành ViewContoder.

Thay vì ViewDidLoad, tôi thêm UITapGestureRecognizer khi TextView hoạt động để chỉnh sửa:

-(void)textViewDidBeginEditing:(UITextView *)textView{
    _tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];

    [self.view addGestureRecognizer: _tapRec];
    NSLog(@"TextView Did begin");
}

Khi tôi nhấn bên ngoài TextView, chế độ xem kết thúc chế độ chỉnh sửa và UITapGestureRecognizer sẽ tự xóa để tôi có thể tiếp tục tương tác với các điều khiển khác trong chế độ xem.

-(void)tap:(UITapGestureRecognizer *)tapRec{
    [[self view] endEditing: YES];
    [self.view removeGestureRecognizer:tapRec];
    NSLog(@"Tap recognized, tapRec getting removed");
}

Tôi hi vọng cái này giúp được. Có vẻ như quá rõ ràng nhưng tôi chưa bao giờ thấy giải pháp này ở bất cứ đâu trên web - tôi có làm gì sai không?


0

Đừng quên đặt đại biểu cho textView - nếu không thì resignfirstresponder sẽ không hoạt động.


0

Thử cái này .

NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];

0

Đối với Xcode 6.4., Swift 1.2. :

   override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent)
    {
        super.touchesBegan(touches, withEvent: event)
        if let touch = touches.first as? UITouch
        {
            self.meaningTextview.resignFirstResponder()
        }
    }

0

Bạn nên thêm UIToolbarvào UITextView hàng đầu để dễ dàng hơn là sử dụngshouldChangeTextIn

Trong Swift 4

let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        toolbar.barStyle = .default
        toolbar.items = [
            UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
            UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(doneAction))
        ]
        textView.inputAccessoryView = toolbar
@objc func doneAction(){
 self.textView.resignFirstResponder()
}

Cho đến nay các giải pháp tốt nhất. Lưu ý rằng thay vì đặt khung, chỉ cần sử dụngtoolbar.sizeToFit()
Fattie
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.