วิธียกเลิกคีย์บอร์ดสำหรับ UITextView พร้อมปุ่มส่งคืน


382

ในห้องสมุดของ IB คำนำบอกเราว่าเมื่อreturnกดแป้นคีย์บอร์ดUITextViewจะหายไป แต่จริงๆแล้วreturnกุญแจสามารถทำหน้าที่เป็น '\ n' เท่านั้น

ฉันสามารถเพิ่มปุ่มและใช้[txtView resignFirstResponder]เพื่อซ่อนแป้นพิมพ์

แต่มีวิธีเพิ่มการกระทำสำหรับreturnคีย์ในแป้นพิมพ์เพื่อที่ฉันไม่ต้องการเพิ่มUIButtonหรือไม่


ทำตามคำแนะนำในโพสต์บล็อกนี้: iphonedevelopertips.com/cocoa/…
ManojN

คำตอบ:


354

UITextViewไม่มีวิธีการใด ๆ ที่จะถูกเรียกเมื่อผู้ใช้พบคีย์ส่งคืน UITextFieldหากคุณต้องการให้ผู้ใช้สามารถเพิ่มเพียงหนึ่งบรรทัดของข้อความให้ใช้ การกดปุ่ม return และซ่อนคีย์บอร์ดสำหรับ a UITextViewนั้นไม่เป็นไปตามแนวทางของอินเตอร์เฟส

แม้ว่าคุณต้องการทำสิ่งนี้ให้ใช้textView:shouldChangeTextInRange:replacementText:วิธีการUITextViewDelegateและในการตรวจสอบว่าข้อความการแทนที่นั้นคือ\nซ่อนคีย์บอร์ดหรือไม่

อาจมีวิธีอื่น แต่ฉันไม่ทราบเลย


1
ขอบคุณและวิธีการทำงานได้ดี เหตุผลในการใช้ UITextView ก็คือมันสามารถเก็บข้อความในหลายบรรทัด และตอนนี้ฉันใช้มันเป็นกล่องข้อความ
Chilly Zhong

28
มันง่ายพอที่จะเปลี่ยนคีย์ส่งคืนเป็น "เสร็จสิ้น" โดยใช้อย่างใดอย่างหนึ่ง[textField setReturnKeyType: UIReturnKeyDone];หรือใช้ตัวสร้างส่วนต่อประสาน
Casebash

9
โอเคตอนนี้ฉันเข้าใจแล้วว่าวิธีการตกแต่งด้วยฟิลด์ข้อความแบบหลายบรรทัดของ Apple คือการเพิ่มสิ่งที่ทำลงในแถบเมนู
Casebash

8
นี่ไม่ใช่วิธีที่ดีในการแก้ไขปัญหานี้เนื่องจากคุณกำลัง จำกัด ผู้ใช้ให้ใช้ Enter เพื่อออกจากคีย์บอร์ด น่าจะเป็นวิธีที่ดีที่สุดคือการเพิ่มปุ่มที่เรียกใช้วิธีการ
Ele

5
@Casebash ดูเหมือนว่าการตั้งค่าคีย์ส่งคืนเป็น "เสร็จสิ้น" ไม่สามารถแก้ปัญหาใน Xcode 6.4, Swift 2.0 ฉันตั้งค่าคีย์โดยใช้ IB
MB_iOSDeveloper

505

คิดว่าฉันจะโพสต์ตัวอย่างได้ที่นี่แทน:

ตรวจสอบให้แน่ใจว่าคุณประกาศการสนับสนุนสำหรับUITextViewDelegateโปรโตคอล

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

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

    return YES;
}

อัพเดต Swift 4.0:

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

75
ปัญหาคือว่านี่ไม่ใช่วิธีการตรวจสอบว่าผู้ใช้เคาะคีย์ส่งคืนแล้ว ผู้ใช้อาจวางอักขระส่งคืนลงในฟิลด์ข้อความและคุณจะได้รับข้อความผู้รับมอบสิทธิ์เดิม โดยทั่วไปคุณใช้มุมมองข้อความในทางที่ผิด วิธียกเลิกคีย์บอร์ดคือ (1) ไม่ต้องทำเลย (เช่นเมื่อเขียนข้อความในแอพ Mail) หรือ (2) เพื่อให้มีปุ่ม Done ที่อื่นในอินเทอร์เฟซ (เช่นในแอพ Notes) คุณสามารถแนบปุ่มดังกล่าวเป็นมุมมองอุปกรณ์เสริมกับแป้นพิมพ์ได้
ด้าน

@ Sam V ข้อมูลโค้ดเป็นผู้ชายที่เท่ห์ มันใช้งานได้สำหรับฉัน ขอบคุณคนตัน มีส่วนย่อยใดบ้างสำหรับการคำนวณแป้นพิมพ์ตัวเลข ขอแสดงความนับถือ shishir
Shishir.bobby

งดงาม. เพียงเตือนความจำว่าในบางสถานการณ์เพื่อกำจัดแป้นพิมพ์ให้ลองทำตามเส้น ... [self.view endEditing: YES];
Fattie

@Vojto ใช้งานได้ดีบน iPad คุณอาจไม่ได้ตั้งตัวแทน
Vincent

4
ปัญหาคือแป้นพิมพ์อาจซ่อนส่วนหนึ่งของอินเทอร์เฟซที่ใช้ในการยกเลิก มันไร้สาระจริง ๆ ที่ IOS ไม่มีปุ่มบนแป้นพิมพ์ทุกปุ่มเพื่อยกเลิกแป้นพิมพ์เพื่อให้ผู้ใช้สามารถทำได้ถ้าต้องการ
Sani Elfishawy

80

ฉันรู้ว่าคำตอบนี้ได้รับการตอบแล้ว แต่ฉันไม่ชอบการใช้สตริงตัวอักษรสำหรับการขึ้นบรรทัดใหม่ดังนั้นนี่คือสิ่งที่ฉันทำ

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

    [txtView resignFirstResponder];
    return NO;
}

อัพเดต 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
ฉันอาจแก้ไขมันเช่นนี้: NSRange resultRange = [text rangeOfCharacterFromSet: [NSCharacterSet newlineCharacterSet] ตัวเลือก: NSBackwardsSearch]; เนื่องจากนี่คือแฮ็กอยู่แล้วดูเหมือนว่าการตรวจสอบจุดสิ้นสุดของการส่งคืนอาจเป็นเส้นทางที่ปลอดภัยกว่า
maxpower

@maxpower ความคิดเห็นดีมาก NSString *replacedText = [textView.text stringByReplacingCharactersInRange:range withString:text]นอกจากนี้ยังจะดีกว่าที่จะตรวจสอบกับข้อความแทนที่เช่น
Rudolf Adamkovič

ลองนึกภาพผู้ใช้วางข้อความที่คัดลอกมาจากที่อื่นที่มีบรรทัดใหม่ พวกเขาอาจจะสับสนเมื่อแทนที่จะเพิ่มข้อความต่อท้ายที่แอปเพียงแค่ยกเลิกคีย์บอร์ด
Nikolai Ruhe

44

ฉันรู้ว่าสิ่งนี้ได้รับการตอบคำถามบ่อยครั้ง แต่นี่เป็นสองเซ็นต์ของฉันสำหรับปัญหา

ฉันพบคำตอบโดยsamvermetteและribetoมีประโยชน์จริง ๆ และยังแสดงความคิดเห็นโดยmaxpowerในคำตอบของribeto แต่มีปัญหากับวิธีการเหล่านั้น ปัญหาที่แมตต์กล่าวถึงในคำตอบของsamvermetteและก็คือถ้าผู้ใช้ต้องการวางบางสิ่งบางอย่างที่มีเส้นแบ่งอยู่ข้างในแป้นพิมพ์จะซ่อนโดยไม่ต้องวางอะไรเลย

ดังนั้นวิธีการของฉันคือการผสมผสานของโซลูชั่นทั้งสามที่กล่าวถึงข้างต้นและตรวจสอบเฉพาะว่าสตริงที่ป้อนเป็นบรรทัดใหม่เมื่อความยาวของสตริงเป็น 1 ดังนั้นเราจึงตรวจสอบให้แน่ใจว่าผู้ใช้พิมพ์แทนการวาง

นี่คือสิ่งที่ฉันได้ทำ:

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

นี่เป็นทางออกที่ดีที่สุดสำหรับปัญหานี้ samvermette answer ไม่ได้คำนึงถึงสถานการณ์ที่ผู้ใช้ต้องการวางข้อความ
marcopaivaf

36

วิธีที่สวยงามกว่าคือการยกเลิกแป้นพิมพ์เมื่อผู้ใช้แตะที่นอกกรอบของแป้นพิมพ์

ก่อนอื่นให้ตั้งค่ามุมมองของ ViewController เป็นคลาส "UIControl" ในตัวตรวจสอบตัวตนใน UIBuilder ควบคุมลากมุมมองไปยังไฟล์ส่วนหัวของ ViewController และเชื่อมโยงมันเป็นแอคชั่นกับเหตุการณ์เช่น Touch Up Inside เช่น:

ViewController.h

-(IBAction)dismissKeyboardOnTap:(id)sender;

ในไฟล์ ViewController หลัก, ViewController.m:

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

คุณสามารถใช้การแตะสองครั้งหรือสัมผัสยาวโดยใช้เทคนิคที่คล้ายกัน คุณอาจต้องตั้งค่า ViewController ของคุณให้เป็น UITextViewDelegate และเชื่อมต่อ TextView กับ ViewController วิธีนี้ใช้ได้กับทั้ง UITextView และ UITextField

ที่มา: Big Nerd Ranch

แก้ไข: ฉันต้องการเพิ่มว่าถ้าคุณใช้ UIScrollView เทคนิคด้านบนอาจไม่ทำงานได้อย่างง่ายดายผ่านตัวสร้างส่วนต่อประสาน ในกรณีนี้คุณสามารถใช้ UIGestureRecognizer และเรียกใช้วิธี [[ดูตัวเอง] endEditing: YES] วิธีการภายในแทน ตัวอย่างจะเป็น:

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

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

เมื่อผู้ใช้แตะที่ด้านนอกของแป้นพิมพ์และไม่ได้แตะพื้นที่รายการแป้นพิมพ์จะถูกยกเลิก


1
ฉันชอบความคิดด้วยGestureRecognizerแต่ปัญหาใหญ่คือปุ่มทั้งหมดหรือตัวควบคุมบนมุมมองนั้นไม่สามารถคลิกได้อีกต่อไป
ผู้เชี่ยวชาญ

34

เพิ่มวิธีนี้ในตัวควบคุมมุมมองของคุณ

รวดเร็ว :

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

วิธีนี้ยังมีประโยชน์สำหรับคุณ:

/**
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
อย่าลืมยืนยันโปรโตคอลUITextViewDelegate :)
swiftBoy

ผมไม่คิดว่ามันเป็นความคิดที่ดีที่จะแทนที่ touchesBegan super.touchesBegan(touches:withEvent:)และไม่ได้โทร
TGO

else { return true }เพื่อแสดงลักษณะสมมาตรของรหัสนี้คุณควรจะเขียน
ความหมาย - สำคัญ

@ ความหมาย - ไม่สำคัญเลย
อเล็กซานเดอร์โวลคอฟ

@AlexanderVolkov คุณไม่ยอมรับว่ามันเป็นสถานการณ์ที่สมมาตรคุณไม่ทราบว่าฉันหมายถึงอะไรคุณไม่เชื่อในคุณค่าของรหัสที่ถูกต้องทางความหมายหรือ ...
ความหมาย - เรื่อง

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

yourtextView.delegate=self;

เพิ่มด้วย UITextViewDelegate

อย่าลืมยืนยันโปรโตคอล

หากคุณไม่ได้เพิ่มif([text isEqualToString:@"\n"])คุณไม่สามารถแก้ไขได้


2
-1 นี่เป็นเพียงคำตอบของ samvermette ที่แย่กว่า คุณพลาดกลับถ้าข้อความจะมีค่าเท่ากับNO @"\n"
devios1

17

มีวิธีแก้ไขปัญหาอื่นในขณะที่ใช้กับ uitextview คุณสามารถเพิ่มแถบเครื่องมือเป็น InputAccessoryView ใน "textViewShouldBeginEditing" และจากปุ่มที่ทำเสร็จแล้วของแถบเครื่องมือนี้คุณสามารถยกเลิกคีย์บอร์ดได้รหัสสำหรับสิ่งต่อไปนี้:

ใน 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]];

ในวิธี textviewdelegate

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

การทำงานของ Button Done ซึ่งอยู่ในแถบเครื่องมือมีดังต่อไปนี้:

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

17

ฉันพบคำตอบโดยjosebamaที่สมบูรณ์และสะอาดที่สุดในกระทู้นี้

ด้านล่างนี้เป็นไวยากรณ์ของSwift 4 :

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
}

resultRangeจุดมุ่งหมายเพื่อทดสอบว่าข้อความที่มีเพียงการขึ้นบรรทัดใหม่ที่หลีกเลี่ยงยากรหัส "\ n"
Qinghua

6

รวดเร็ว

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

และกำหนดค่า


ภาพหน้าจอนั้นมาจากไหน
แซม

6

การใช้ตัวควบคุมทิศทางเพื่อโฮสต์บาร์เพื่อปิดคีย์บอร์ด:

ในไฟล์. h:

UIBarButtonItem* dismissKeyboardButton;

ในไฟล์. 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

เช่นเดียวกับความคิดเห็นแบบด้านถึง samvermette ฉันไม่ชอบความคิดในการตรวจจับ "\ n" เช่นกัน ปุ่ม "return" มีไว้สำหรับเหตุผลใน UITextView นั่นคือไปที่บรรทัดถัดไปของหลักสูตร

ทางออกที่ดีที่สุดในความคิดของฉันคือการเลียนแบบแอปข้อความของ iPhone - ซึ่งก็คือการเพิ่มแถบเครื่องมือ (และปุ่ม) บนแป้นพิมพ์

ฉันได้รับรหัสจากโพสต์บล็อกดังต่อไปนี้:

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

ขั้นตอน:

เพิ่มแถบเครื่องมือลงในไฟล์ XIB ของคุณ - ตั้งค่าความสูงเป็น 460

- เพิ่มรายการปุ่มแถบเครื่องมือ (หากยังไม่ได้เพิ่ม) หากคุณต้องการจัดแนวขวาให้เพิ่มรายการปุ่มแถบยืดหยุ่นลงใน XIB และย้ายรายการปุ่มแถบเครื่องมือ

- สร้างแอคชั่นที่เชื่อมโยงรายการปุ่มของคุณเพื่อลาออกก่อนตอบกลับดังนี้:

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

-Then:

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

ปิดหัวข้อ แม้ว่าโซลูชันของคุณจะสวยงาม แต่ก็ไม่ตอบคำถามเดิม: "จะยกเลิกคีย์บอร์ดสำหรับ UITextView ด้วยปุ่มส่งคืนได้อย่างไร" มีสถานการณ์เมื่อใช้ UITextView เพื่อจำลองการตัดคำ UITextField ไม่ใช่การป้อนหลายบรรทัด
SwiftArchitect

2
แม้ว่าจะไม่ได้อยู่ในหัวข้อ แต่ก็มีประโยชน์มาก ฉันต้องการให้ UITextView ป้อนด้วยหลายบรรทัดและยกเลิกคีย์บอร์ดเมื่อต้องการ
เหยิง

5

เพียงแก้ไขปัญหานี้ในแบบที่ต่างออกไป

  • สร้างปุ่มที่จะวางไว้ในพื้นหลัง
  • จากตัวตรวจสอบคุณสมบัติเปลี่ยนประเภทปุ่มเป็นกำหนดเองและทำให้ปุ่มโปร่งใส
  • ขยายปุ่มเพื่อให้ครอบคลุมมุมมองทั้งหมดและตรวจสอบให้แน่ใจว่าปุ่มนั้นอยู่ด้านหลังวัตถุอื่นทั้งหมด วิธีง่ายๆในการทำเช่นนี้คือการลากปุ่มไปที่มุมมองด้านบนของรายการในมุมมอง
  • ควบคุมการลากปุ่มไปที่viewController.hไฟล์และสร้างการกระทำ (เหตุการณ์ที่ส่ง: Touch Up Inside) เช่น:

    (IBAction)ExitKeyboard:(id)sender;
  • ในViewController.mควรมีลักษณะดังนี้:

    (IBAction)ExitKeyboard:(id)sender {
        [self.view endEditing:TRUE];
    }
  • เรียกใช้แอพและเมื่อคุณคลิกออกจาก TextView คีย์บอร์ดจะหายไป

คุณต้องเพิ่ม: - (เป็นโมฆะ) textViewDidEndEditing: (UITextView *) textView {[self.TextView quitFirstResponder]; }
samouray

5

เพิ่มผู้สังเกตการณ์ใน viewDidLoad

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

จากนั้นใช้ตัวเลือกเพื่อตรวจสอบ "\ n"

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

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

มันใช้ "\ n" และไม่ได้ตรวจสอบคีย์ส่งคืนโดยเฉพาะ แต่ฉันคิดว่ามันโอเค

UPDATE

ดูคำตอบของ ribto ด้านล่างซึ่งใช้[NSCharacterSet newlineCharacterSet]แทน\n


ข้อผิดพลาดจะใช้\nและตรวจพบคีย์ส่งคืนตาม\nดังนั้นจึงตรวจสอบคีย์ส่งคืน ข้อแตกต่างคือคุณใช้การแจ้งเตือนมากกว่าการใช้ textViewDelegates
GoodSp33d

ตอนนี้ฉันคิดว่าการตรวจสอบ [NSCharacterSet newlineCharacterSet]มากกว่า \ n อาจเป็นวิธีที่ดีกว่า
ToddB

5

รหัสสวิฟท์

ใช้ UITextViewDelegate ในชั้นเรียนของคุณ / ดูดังนี้:

class MyClass: UITextViewDelegate  { ...

ตั้งค่าตัวแทน textView เป็นตนเอง

myTextView.delegate = self

จากนั้นใช้สิ่งต่อไปนี้:

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

แก้ไข ฉันอัปเดตรหัสเพราะไม่ควรเปลี่ยนอินพุตของผู้ใช้ในฟิลด์ข้อความเป็นวิธีการแก้ปัญหาและไม่รีเซ็ตสถานะหลังจากโค้ดแฮ็คเสร็จสมบูรณ์


4

ลองสิ่งนี้:

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

    return YES;

}

4

// คุณสามารถใช้สิ่งนี้ ...

ขั้นตอนที่ 1 ขั้นตอนแรกคือการทำให้แน่ใจว่าคุณประกาศการสนับสนุนสำหรับUITextViewDelegateโปรโตคอล สิ่งนี้ทำได้ในไฟล์ส่วนหัวของคุณตัวอย่างเช่นที่นี่คือส่วนหัวที่เรียก

EditorController.h:

@interface EditorController : UIViewController  {
  UITextView *messageTextView;
}

@property (nonatomic, retain) UITextView *messageTextView;

@end

ขั้นตอนที่ 2 ถัดไปคุณจะต้องลงทะเบียนคอนโทรลเลอร์ในฐานะตัวแทนของ UITextView ต่อจากตัวอย่างข้างต้นนี่คือวิธีที่ฉันได้เริ่มต้นUITextViewด้วยEditorControllerในฐานะตัวแทน ...

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

ขั้นตอนที่ 3 และตอนนี้ชิ้นส่วนสุดท้ายของตัวต่อคือการดำเนินการเพื่อตอบสนองต่อshouldCahngeTextInRangeข้อความดังต่อไปนี้:

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

คุณยังสามารถซ่อนแป้นพิมพ์เมื่อสัมผัสในหน้าจอดู:

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

IMHO นี่เป็นวิธีการที่ดีมากดีกว่าปุ่มที่ครอบคลุมทุกมุมมอง
WebOrCode

3

คำตอบที่รวดเร็ว:

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

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

3

ฉันใช้รหัสนี้เพื่อเปลี่ยนการตอบกลับ

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

    }

ทำไมไม่ใช้ [self.view endEditing: YES]; ครั้งเดียว ??
ajay_nasa

3

คำถามถามว่าจะทำอย่างไรกับคีย์ส่งคืน แต่ฉันคิดว่านี่อาจช่วยคนที่มีเจตนาจะทำให้คีย์บอร์ดหายไปเมื่อใช้ 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()
}

เรียกใช้addToolBarForTextView ()ในviewDidLoadหรือวิธีวงจรชีวิตอื่น ๆ

ดูเหมือนว่าเป็นทางออกที่สมบูรณ์แบบสำหรับฉัน

ไชโย

Murat


1
สำหรับปี 2019ตอนนี้คัดลอกและวางไม่มีข้อผิดพลาดทางไวยากรณ์และการตั้งชื่อปัจจุบัน
Fattie

1
โดยคำตอบที่ดีที่สุดที่นี่ ฉันเพิ่งแก้ไขข้อผิดพลาดทางไวยากรณ์ที่เรียบง่ายแน่นอนการแก้ไขตามที่คุณต้องการ ขอบคุณ!
Fattie

2

ตกลง. ทุกคนได้ให้คำตอบกับลูกเล่น แต่ฉันคิดว่าวิธีที่ถูกต้องในการบรรลุเป้าหมายนี้ก็คือ

การเชื่อมต่อการดำเนินการต่อไปนี้ " ไม่สิ้นสุดในวันที่ออกจาก " Interface Builderเหตุการณ์ใน (คลิกขวาTextFieldและลาก cntrl จาก ' Did end on exit ' ไปยังวิธีการต่อไปนี้

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

6
-1 คำถามเกี่ยวกับ UITextView ไม่ใช่ UITextField เพื่อนของฉัน
Yogi

2
คำตอบเหล่านี้ส่วนใหญ่อยู่ที่นี่ด้วยคะแนนเพราะเหมาะสมกับสถานการณ์ที่หลากหลายของนักพัฒนาที่แตกต่างกัน
carbonr

หากคุณใช้ UITextField นี่เป็นวิธีที่จะทำ BTW คุณควรใช้ YES / NO สำหรับ Objective-C BOOLs ไม่ใช่ TRUE / FALSE
Jon Shier

1
@jshier: จริง / เท็จก็โอเค
โยคี

2

คล้ายกับคำตอบอื่น ๆ ที่ใช้UITextViewDelegateอินเทอร์เฟซ swift ที่ใหม่กว่าisNewline:

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

ฉันรู้ว่ามันไม่ใช่คำตอบที่แน่นอนสำหรับคำถามนี้ แต่ฉันพบกระทู้นี้หลังจากตามล่าหาอินเทอร์เน็ตเพื่อหาคำตอบ ฉันคิดว่าคนอื่นแบ่งปันความรู้สึกนั้น

นี่คือความแปรปรวนของฉันของ UITapGestureRecognizer ซึ่งฉันพบว่าเชื่อถือได้และใช้งานง่าย - เพียงแค่ตั้งค่ามอบหมายของ TextView เป็น ViewController

แทน ViewDidLoad ฉันเพิ่ม UITapGestureRecognizer เมื่อ TextView ใช้งานเพื่อแก้ไข:

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

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

เมื่อฉันแตะนอก TextView มุมมองจะสิ้นสุดโหมดแก้ไขและ UITapGestureRecognizer จะลบตัวเองออกเพื่อให้ฉันสามารถโต้ตอบกับตัวควบคุมอื่น ๆ ในมุมมองต่อไปได้

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

ฉันหวังว่านี่จะช่วยได้. ดูเหมือนชัดเจนมาก แต่ฉันไม่เคยเห็นโซลูชันนี้มาจากที่ใดบนเว็บ - ฉันกำลังทำอะไรผิดหรือเปล่า?


0

อย่าลืมตั้งค่าผู้รับมอบสิทธิ์ให้กับ textView มิฉะนั้นการลาออกของผู้ตอบแบบสอบถามจะไม่ทำงาน



0

สำหรับ 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

คุณควรเพิ่มUIToolbarไว้ที่ UITextView ด้านบนเพื่อให้ง่ายกว่าการใช้shouldChangeTextIn

ใน 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()
}

โดยทางออกที่ดีที่สุด โปรดทราบว่าแทนที่จะตั้งกรอบให้ใช้toolbar.sizeToFit()
Fattie
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.