ปิดแป้นพิมพ์โดยแตะพื้นหลังของ UITableView


105

ฉันมีUITableViewกับUITextFields เป็นเซลล์ ฉันต้องการที่จะยกเลิกแป้นพิมพ์เมื่อพื้นหลังของที่UITableViewถูกสัมผัส ฉันพยายามทำสิ่งนี้โดยสร้างUIButtonขนาดของUITableViewและวางไว้ด้านหลังไฟล์UITableView. ปัญหาเดียวคือการUIButtonจับทุกการสัมผัสแม้ว่าการสัมผัสจะอยู่บน UITableView ก็ตาม ผมทำอะไรผิดหรือเปล่า?

ขอบคุณ!


คำถามและคำตอบ releated: Q1 , Q2 , Q3
Yantao Xie

นี่คือคำตอบที่ดีที่สุดstackoverflow.com/a/12851794/1418457
onmyway133

คำตอบ:


203

สิ่งนี้ทำได้อย่างง่ายดายโดยการสร้างวัตถุUITapGestureRecognizer (โดยค่าเริ่มต้นสิ่งนี้จะตรวจจับ "ท่าทางสัมผัส" ในการแตะเพียงครั้งเดียวดังนั้นจึงไม่จำเป็นต้องปรับแต่งเพิ่มเติมอีก) ระบุเป้าหมาย / การกระทำเมื่อท่าทางถูกยิงจากนั้นแนบวัตถุจดจำท่าทาง ไปยังมุมมองตารางของคุณ

เช่นบางทีในviewDidLoadวิธีการของคุณ:

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

และhideKeyboardวิธีการอาจมีลักษณะดังนี้:

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

สังเกตว่าท่าทางจะไม่เริ่มทำงานเมื่อสัมผัสภายในUITextFieldวัตถุ มันถูกยิงบนUITableViewพื้นหลังมุมมองส่วนท้ายมุมมองส่วนหัวและในUILabelsเซลล์ภายในเป็นต้น


4
เมื่อฉันลองสิ่งนี้ฉันพบว่ามันทำให้ตารางไม่สามารถเลือกเซลล์ได้ :( วิธีแก้ปัญหาที่ยอดเยี่ยมอย่างอื่น
Brian

109
ในฐานะที่เป็นแนวทางในการแก้ปัญหาชี้ให้เห็นว่าคุณสามารถทำให้งานนี้ดีขึ้นมากโดยตั้งค่า:gestureRecognizer.cancelsTouchesInView = NO;
Zebs

3
และอย่าลืมปล่อย GestureRecognizer เมื่อต่อเข้ากับ tableView แล้ว
Paul Lynch

39
สำหรับวิธีการแทนในการติดต่อสื่อสารโดยตรงกับช่องข้อความที่คุณสามารถทำได้hideKeyboard [self.view endEditing:NO];จาก Apple docs: " วิธีนี้จะดูมุมมองปัจจุบันและลำดับชั้นมุมมองย่อยสำหรับฟิลด์ข้อความที่ปัจจุบันเป็นผู้ตอบกลับคนแรกหากพบช่องข้อความนั้นจะขอให้ช่องข้อความนั้นลาออกในฐานะผู้ตอบคนแรกหากพารามิเตอร์บังคับถูกตั้งค่าเป็น ใช่ช่องข้อความไม่เคยถามด้วยซ้ำมันถูกบังคับให้ลาออก "
Gobot

1
ใช้วิธีนี้วิธี "didSelectRowAtIndexPath" ของฉันไม่ได้รับการเรียก ทางออกใดสำหรับสิ่งนี้ ??
uniruddh

127

โซลูชัน UITapGestureRecognizer ทำงานร่วมกับการเลือกเซลล์ตารางหากคุณตั้งค่า:

gestureRecognizer.cancelsTouchesInView = NO;

1
สิ่งนี้อนุญาตให้สัมผัสเซลล์ แต่ท่าทางจะถูกจดจำเช่นกันบางทีเราควรใช้วิธีการมอบหมายนี้shouldReceiveTouch
onmyway133

61

นี่คือวิธีที่ดีที่สุดในการดำเนินการนี้ เพียงแค่ทำสิ่งนี้

[self.view endEditing:YES];

หรือ

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

ฉันควรใส่รหัสนี้ไว้ที่ไหน ขอโทษฉันมือใหม่ และโปรดระบุรหัสที่รวดเร็ว
John

54

คุณสามารถทำได้จาก Storyboard: ใส่คำอธิบายภาพที่นี่


1
สิ่งที่ฉันเลือก: ปิดเมื่อลากปิดโต้ตอบเมื่อฉันแตะเซลล์ตารางเซลล์นั้นจะถูกเลือก ฉันใช้ Xcode 8, swift 3 โปรดช่วยด้วย
John

22

ในฐานะที่UITableViewเป็นคลาสย่อยของUIScrollViewการใช้วิธีการมอบหมายหนึ่งวิธีด้านล่างนี้เป็นวิธีแก้ปัญหาที่ง่ายและรวดเร็วมาก ไม่จำเป็นต้องเกี่ยวข้องด้วยซ้ำresignFirstResponderตั้งแต่ดูข้อมูลลำดับชั้นและค้นหาผู้ตอบกลับปัจจุบันและขอให้ลาออกจากสถานะผู้ตอบ

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

และอย่าลืมเพิ่มลงUIScrollViewDelegateในไฟล์ส่วนหัว


2
สามารถทำได้ผ่านซับเดียวนี้ตามที่ @Joe Masilotti ระบุหากคุณกำหนดเป้าหมาย iOS7 ขึ้นไป: self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
atulkhatri

จะเกิดอะไรขึ้นถ้าคุณแตะที่ช่องข้อความที่ด้านล่างของหน้าจอซึ่งควรจะเลื่อนขึ้นเพื่อแสดงแป้นพิมพ์ - แป้นพิมพ์ของคุณจะถูกซ่อน
Islam Q.

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

13

ประการแรกฟังscrollViewWillBeginDraggingในของคุณUIViewControllerโดยเพิ่มUIScrollViewDelegate:

ในไฟล์. h:

@interface MyViewController : UIViewController <UIScrollViewDelegate> 

ในไฟล์. m:

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

    [self dismissKeyboard];

}

จากนั้นฟังการโต้ตอบอื่น ๆ :

- (void)setupKeyboardDismissTaps {

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

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

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

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


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

}

จากนั้นใช้dismissKeyboard:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    [yourTextFieldPointer resignFirstResponder];

}

และถ้าเช่นฉันคุณต้องการปิดแป้นพิมพ์สำหรับ UITextField ภายในเซลล์ตารางที่กำหนดเอง:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

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

}

หวังว่าจะช่วยให้ทุกคนค้นหา !!



8

นี่คือเวอร์ชันที่รวดเร็วเพื่อความสุขในการเขียนโค้ดของคุณ:

เพิ่มเครื่องมือจดจำท่าทางสัมผัสจากนั้นปิดแป้นพิมพ์ ไม่จำเป็นต้องมีทางออกสำหรับ TextField!

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

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

1
สิ่งนี้ใช้ได้แม้กับ tableViewCell ที่กำหนดเอง! ฉันใช้เวลามากในการพยายามคิดออก ขอบคุณมาก! คุณคือฮีโร่ของฉัน youtu.be/EqWRaAF6_WY
peacetype

8

มีเวอร์ชัน Swift 3 ที่ไม่มีการปิดกั้นการแตะบนเซลล์

ในviewDidLoad()วิธีการ:

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

และhideKeyboardมีลักษณะดังนี้:

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

7

ฉันทำแบบนี้:

สร้างเมธอดใน TableViewController ของคุณเพื่อปิดใช้งานการตอบกลับแรก (ซึ่งจะเป็นกล่องข้อความของคุณ ณ จุดนั้น)

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

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

ในการtableView:didSelectRowAtIndexPath:โทรวิธีก่อนหน้านี้:

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

คุณทำผิดในแบบที่คุณถาม คุณไม่ได้ใส่ปุ่มบนมุมมองที่คุณบอกให้มุมมองถอดแป้นพิมพ์ออกเหมือนคำตอบนี้

2
สิ่งนี้จะทำงานได้อย่างสวยงามหากคุณแตะภายในเซลล์มุมมองตาราง (และภายนอก UITextField ใด ๆ ภายในเซลล์มุมมองตารางนั้น) อย่างไรก็ตามหากฉันแตะพื้นหลังของมุมมองตาราง (ซึ่งมักจะเป็นเป้าหมายที่ง่ายกว่าในการไปที่ - กฎของ yay Fitts!) เป็นจริงตามที่คาดไว้เนื่องจากเรากำลังดำเนินการนี้ภายใน tableView: didSelectRowAtIndexPath :. หากสิ่งนี้สามารถปรับเปลี่ยนได้เพื่อให้ทำงานกับการแตะที่อื่นในมุมมองตาราง (ซึ่งจะไม่ต้องการโฟกัสแป้นพิมพ์) ฉันคิดว่าเรามีผู้ชนะที่นี่แล้ว!
Joe D'Andrea

ฉันมีปัญหาเดียวกันกับ jdandrea ซึ่งdidSelectRowAtIndexPathจะไม่เริ่มทำงานหากคุณแตะ TableView เอง
zekel

หาก didSelectRowAtIndexPath ไม่เพียงพอให้ทำเช่นเดียวกันใน TouchBegan เช่นกัน!
Amogh Talpallikar

5

ฉันมีUITableViewControllerและการใช้งานtouchesBegan:withEvent:ไม่ได้ผลสำหรับฉัน

นี่คือสิ่งที่ได้ผล:

รวดเร็ว:

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

วัตถุประสงค์ -C:

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

ความคิดที่ดีฉันชอบมัน
HotFudgeSunday

4
@interface DismissableUITableView : UITableView {
}
@end

@implementation DismissableUITableView

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

@end

จากนั้นตรวจสอบให้แน่ใจว่าในไฟล์ Nib ของคุณคุณตั้งค่าประเภทของ UITableView ของคุณเป็น DismissableUITableView ..... บางทีฉันอาจจะคิดชื่อที่ดีกว่าสำหรับคลาสนี้ แต่คุณเข้าใจถูกแล้ว


4

หากคุณกำหนดเป้าหมายเป็น iOS7 คุณสามารถใช้สิ่งใดสิ่งหนึ่งต่อไปนี้:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

ก่อนหน้านี้จะทำให้แป้นพิมพ์เคลื่อนไหวออกจากหน้าจอเมื่อมีการเลื่อนมุมมองตารางและในภายหลังจะซ่อนแป้นพิมพ์เช่นเดียวกับแอปข้อความหุ้น

โปรดทราบว่าสิ่งเหล่านี้มาจากUIScrollViewซึ่งUITableViewสืบทอดมาจาก


ดี. ฉันจัดการแบ่งประเภทของมันได้โดยการปัดลงจากที่สูงขึ้นบนหน้าจอจนกระทั่งแป้นพิมพ์เริ่มเลื่อนลงจากนั้นปัดกลับขึ้นจนกว่าแป้นพิมพ์จะเลื่อนขึ้นเล็กน้อยแล้วจึงปล่อย มุมมองแบบเลื่อนไม่กลับไปด้านบนเท่าที่ควร
แซม

3

ลองสิ่งนี้:

viewDidLoad(){

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

    tableView.addGestureRecognizer(tap)

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

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

}

2

UITableView เป็นคลาสย่อยของ UIScrollView

วิธีที่ฉันทำคือการฟังเหตุการณ์เลื่อนโดยผู้ใช้แล้วลาออกก่อนตอบกลับ นี่คือวิธี UIScrollViewDelegate ที่จะใช้ในโค้ดของคุณ

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

เมื่อเข้าใกล้ปัญหาประเภทนี้ฉันพบวิธีที่ดีที่สุดคือการค้นคว้าโปรโตคอลตัวแทนสำหรับแต่ละออบเจ็กต์และคลาสพาเรนต์ (ในกรณีนี้คือ UITableViewDelegate, UIScrollViewDelegate จำนวนเหตุการณ์ที่วัตถุ NS ยิงนั้นค่อนข้างใหญ่และครอบคลุม นอกจากนี้ยังใช้โปรโตคอลได้ง่ายขึ้นจากนั้นก็ทำการคลาสย่อยอะไรก็ได้


2

ฉันมีปัญหาเดียวกันและนี่คือวิธีแก้ปัญหาของฉันมันทำงานได้ดีสำหรับฉัน:

ในมุมมองหรือตัวควบคุมมุมมองที่คุณใช้งาน <UITextFieldDelegate>

(ในกรณีของฉันฉันมีแบบกำหนดเองที่UITableViewCellเรียกว่า TextFieldCell)

ประกาศUITapGestureRecognizerเป็นคุณสมบัติ:

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

และเริ่มต้นในมุมมอง / ตัวควบคุมของคุณ:

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

ใน- (void)textFieldDidBeginEditing:(UITextField *)textFieldวิธีนี้ใช้superViewเพื่อเลื่อนขึ้นไปที่ tableView ของคุณและโทรaddGestureRecognizer:

[self.superview.superview addGestureRecognizer:gestureRecognizer];

และใน- (void)textFieldDidEndEditing:(UITextField *)textFieldเพียงแค่ลบตัวจดจำท่าทาง:

[self.superview.superview removeGestureRecognizer:gestureRecognizer];

หวังว่าจะช่วยได้


สิ่งนี้ทำเพื่อฉัน ขอบคุณ hac.jack
gilsaints88

2

ฉันต้องการให้เซลล์ของฉันเปิดแป้นพิมพ์เมื่อมีการเลือกส่วนใดส่วนหนึ่งของเซลล์และปิดหากคุณคลิกที่ใดก็ได้จากเซลล์นั้น ในการเปิดแป้นพิมพ์:

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

(หมายเหตุ: ฉันได้คลาสย่อยของเซลล์แล้ว แต่คุณสามารถทำได้อย่างง่ายดายในtableView:didSelectRowAtIndexPath:วิธีการมอบหมายของUITableView)

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

วิธีแก้ไขคือตรวจสอบว่าการคลิกเกิดขึ้นภายในเซลล์ที่เลือกในปัจจุบันหรือไม่:

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

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

2

ฉันพบวิธีแก้ปัญหาที่ใช้งานได้ดี

เป็นสิ่งจำเป็นที่จะใช้UIGestureRecognizerDelegateและวิธีการ- gestureRecognizer: shouldReceiveTouch:

เพิ่มเครื่องมือจดจำท่าทางไปยัง TableView ดังนี้:

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

จากนั้นใช้เมธอดผู้แทนshouldReceiveTouchเพื่อปฏิเสธการสัมผัสที่ดำเนินการในคลาส UITableViewCell hideKeyboardวิธีเดียวที่จะถูกเรียกเมื่อสัมผัสได้รับการดำเนินการนอกชั้น UITableViewCell

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

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

2

UITableViewมีbackgroundViewคุณสมบัติที่สะดวกซึ่งฉันทำพฤติกรรมนี้ได้โดยไม่ต้องยุ่งกับการเลือกเซลล์ดังที่แสดงด้านล่างใน Swift:

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

1

ฉันกำลังค้นหาวิธีแก้ปัญหาและไม่พบสิ่งใดที่เหมาะกับรหัสของฉันดังนั้นฉันจึงทำเช่นนี้:

http://82517.tumblr.com/post/13189719252/dismiss-keyboard-on-uitableview-non-cell-tap

โดยพื้นฐานแล้วเป็นการผสมผสานระหว่างแนวทางที่กล่าวถึงก่อนหน้านี้ แต่ไม่จำเป็นต้องมีคลาสย่อยหรือสร้างปุ่มพื้นหลัง


1

เพียงใช้ UITapGestureRecognizer และcancelsTouchesInView = NOหมายความว่าการแตะที่เซลล์และ UITextViews ก็ทริกเกอร์การซ่อนเช่นกัน สิ่งนี้ไม่ดีหากคุณมี UITextView หลายรายการและคุณแตะที่รายการถัดไป แป้นพิมพ์จะเริ่มซ่อนจากนั้น textView ถัดไปจะกลายเป็นคำตอบแรกและแป้นพิมพ์จะปรากฏขึ้นอีกครั้ง เพื่อหลีกเลี่ยงปัญหานี้ให้ตรวจสอบตำแหน่งการแตะและซ่อนแป้นพิมพ์หากการแตะไม่ได้อยู่ในเซลล์:

// 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:การเรียกใช้scrollEnabledคุณสมบัติของ tableView ต้องเป็นYES

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

เหมาะสำหรับฉัน เพิ่ม texbox ไปยังเซลล์ tableview ถ้าฉันแตะด้านนอกแป้นพิมพ์ปิด
Nicola

0

ทำไมคุณถึงต้องการสร้างตารางที่เต็มไปด้วยฟิลด์ข้อความ คุณควรใช้มุมมองโดยละเอียดสำหรับแต่ละแถวที่มีช่องข้อความ เมื่อคุณพุช detailview ของคุณตรวจสอบให้แน่ใจว่าคุณเรียก "[myTextField becomeFirstResponder]" เพื่อให้ผู้ใช้สามารถเริ่มแก้ไขได้โดยคลิกเพียงครั้งเดียวจากรายการตาราง


แอพผู้ติดต่อของ Apple ทำสิ่งนี้ได้อย่างแม่นยำ ฉันจะไม่บอกว่ามันเต็มไปด้วยช่องข้อความต่อตัว แต่มันใช้มันเพื่อเอฟเฟกต์ที่ดี
Joe D'Andrea

2
การแก้ไขข้อความแบบอินไลน์ในมุมมองตารางนั้นรวดเร็วและใช้งานง่ายกว่าการผลักดันมุมมองรายละเอียดสำหรับทุกช่องข้อความที่ผู้ใช้ต้องการแก้ไข ... เพียงแค่ถามแบบฟอร์ม HTML ที่ใกล้ที่สุดของคุณหรือฟิลด์ข้อความในบานหน้าต่างการตั้งค่า iPhone หรือแอพผู้ติดต่อหรือ ฯลฯ และอื่น ๆ ... เป็นเรื่องที่น่าเสียดายอย่างยิ่งที่ Apple ไม่ได้ทำให้เป็นประเภทเซลล์มาตรฐาน แต่มีข้อมูลมากมายบนเว็บเกี่ยวกับการบรรลุสิ่งนี้
glenc

0

หากคุณยินดีที่จะคลาสย่อย (ฮึ!) มุมมองตารางของคุณสิ่งนี้อาจใช้ได้:

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

   BOOL backgroundTouched = YES;

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

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

   [super touchesBegan:touches withEvent:event];
}

0

หากคุณต้องการปิดแป้นพิมพ์ในขณะที่กดปุ่มย้อนกลับคุณสามารถเพิ่มรหัสต่อไปนี้ใน textField ควรส่งคืนวิธีการคือ:

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

ช่องข้อความบางช่องอาจมีมุมมองตัวเลือกหรืออื่น ๆ เป็นมุมมองย่อยดังนั้นในกรณีนี้วิธีการข้างต้นไม่ได้ผลดังนั้นในกรณีนี้เราจำเป็นต้องใช้ประโยชน์จากคลาส UITapGestureRecognizer เช่นเพิ่มข้อมูลโค้ดต่อไปนี้ในเมธอด viewDidLoad เช่น:

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

    [self.view addGestureRecognizer:tap];

ตอนนี้เพียงเพิ่มผู้ตอบกลับการลาออกในวิธีการเลือกเช่น:

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

หวังว่าจะช่วยได้ขอบคุณ :)


0

คำตอบที่น่าสนใจมากมาย ฉันต้องการรวบรวมแนวทางต่างๆในโซลูชันที่ฉันคิดว่าเหมาะสมกับสถานการณ์ UITableView มากที่สุด (เป็นวิธีที่ฉันมักจะใช้): สิ่งที่เราต้องการโดยทั่วไปคือการซ่อนแป้นพิมพ์ในสองสถานการณ์: เมื่อแตะด้านนอกองค์ประกอบ UI ของข้อความ หรือในการเลื่อนลง / ขึ้น UITableView สถานการณ์แรกที่เราสามารถเพิ่มได้อย่างง่ายดายผ่าน TapGestureRecognizer และครั้งที่สองผ่านวิธี UIScrollViewDelegate scrollViewWillBeginDragging: ลำดับแรกของธุรกิจวิธีซ่อนแป้นพิมพ์:

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

    }

วิธีนี้จะลาออกจาก UI ของ textField ของมุมมองย่อยภายในลำดับชั้นมุมมอง UITableView ดังนั้นจึงเป็นประโยชน์มากกว่าการลาออกทุกองค์ประกอบอย่างเป็นอิสระ

ต่อไปเราจะดูแลการปิดโดยใช้ท่าทางสัมผัสภายนอกโดย:

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

}

- (void)setupKeyboardDismissGestures
{

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

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

}

การตั้งค่า tapGestureRecognizer.cancelsTouchesInView เป็น NO คือการหลีกเลี่ยงไม่ให้ท่าทาง

ในที่สุดเพื่อจัดการกับการซ่อนแป้นพิมพ์ในการเลื่อนขึ้น / ลง UITableView เราต้องใช้โปรโตคอล UIScrollViewDelegate scrollViewWillBeginDragging: method เป็น:

.h ไฟล์

@interface MyViewController : UIViewController <UIScrollViewDelegate>

.m ไฟล์

#pragma mark - UIScrollViewDelegate

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

ฉันหวังว่ามันจะช่วยได้! =)


0

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

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

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

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

[self.view addGestureRecognizer:tapGesture];

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

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

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

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

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

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

   CGFloat keyboardHeight = keyboardSize.height;

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

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

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

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

0

คำตอบของ @ mixca มีประโยชน์มาก แต่ถ้าฉันมีบางอย่างที่แตกต่างจาก UITextField ฉันคิดว่าวิธีที่ดีที่สุดในการจัดการโดยการค้นหามุมมองย่อยทั้งหมดของมุมมองหลักด้วยฟังก์ชันเรียกซ้ำดูตัวอย่างด้านล่าง

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

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

และคุณสามารถใส่วิธีนี้ในคลาสยูทิลิตี้ของคุณและสามารถใช้จากท่าทางสัมผัสเช่นคำตอบของ @ mixca ..


0

สวิฟต์ 4 / 4.2 / 5

คุณยังสามารถปิดแป้นพิมพ์ได้เมื่อมีการแตะเซลล์ก่อนที่จะดำเนินการอย่างอื่น

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

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