แป้นพิมพ์ iPad จะไม่ยกเลิกหากรูปแบบการนำเสนอ ViewController เป็นกิริยาช่วยเป็น UIModalPresentationFormSheet


214

บันทึก:

ดูคำตอบที่ยอมรับ (ไม่ได้รับการโหวตสูงสุด) สำหรับวิธีแก้ปัญหาตั้งแต่ iOS 4.3

นี้คำถามที่เป็นเรื่องเกี่ยวกับพฤติกรรมที่พบในแป้นพิมพ์ iPad ที่จะปฏิเสธที่จะถูกไล่ออกถ้าแสดงในกิริยาโต้ตอบกับตัวควบคุมนำทาง

โดยทั่วไปถ้าฉันแสดงตัวควบคุมการนำทางด้วยบรรทัดต่อไปนี้:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

แป้นพิมพ์ปฏิเสธที่จะถูกไล่ออก หากฉันใส่ความคิดเห็นในบรรทัดนี้แป้นพิมพ์ก็หายไป

...

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

WORKS

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
[self.view addSubview:b.view];

ไม่ทำงาน, ไม่เป็นผล

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
[[UINavigationController alloc]
 initWithRootViewController:b];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];

ถ้าฉันลบส่วนควบคุมการนำทางและแสดง 'b' เป็นตัวควบคุมมุมมอง modal เองมันทำงาน ตัวควบคุมการนำทางมีปัญหาหรือไม่

WORKS

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
b.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:b animated:YES];
[b release];

WORKS

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
    [[UINavigationController alloc]
         initWithRootViewController:b];
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];

คำถาม SO ต่อไปนี้ดูเหมือนว่าจะมีปัญหาเดียวกัน แต่ไม่มีคำตอบ: stackoverflow.com/questions/3019709/ …
Kalle

+1 ขอบคุณสำหรับคำอธิบายที่ดี แต่ฉันจะต้องวางวิธีการที่? ดูเหมือนไม่ได้ทำงานที่ฉันสร้างรหัสสำหรับการนำเสนอรูปแบบการควบคุม ...
Lorenzo B

1
มันจะต้องอยู่ในระดับควบคุมมุมมองกิริยา
Kalle

ขอบคุณ ฉันเห็น. ฉันแก้ไขมันไว้ในหมวดหมู่สำหรับUINavigationControllerชั้นเรียน ไชโย
Lorenzo B

ฉันเป็นหนี้บุญคุณคุณสำหรับคำถามนี้ ฉันประหลาดใจที่resignFirstResponderกำลังดำเนินการ แต่แป้นพิมพ์ยังคงปรากฏอยู่ สถานการณ์ของฉัน (PresentationFormSheet พร้อมการนำทาง contrllr) นั้นเหมือนกับของคุณทุกประการ ขอบคุณตัน !!
sErVerdevIL

คำตอบ:


115

ในตัวควบคุมมุมมองที่แสดงแบบโมดัลเพียงแทนที่disablesAutomaticKeyboardDismissalเพื่อส่งคืนNO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

ใช่ตั้งแต่ 4.3 นี่น่าจะเป็นกรณี จะอัปเดตคำถาม ขอบคุณ!
Kalle

2
ต้องเพิ่มสิ่งนี้ลงในตัวควบคุมการนำทาง
pottedmeat

1
ใช่ทำงานเมื่อคุณเขียนทับใน NavigationController นั่นเป็นสิ่งเดียวที่ใช้งานได้จริงสำหรับฉัน
James Laurenstin

ช่วยชีวิต! ทำไม Apple ทำสิ่งนี้ แน่นอนมันควรจะเริ่มต้นกับ NO และช่วยให้เราสามารถเปลี่ยนได้ถ้าเราอยากจะ
SomaMan

ไม่ทำงานบน UIViewController คลาสที่ได้รับปิดการใช้งาน
อัตโนมัติคีบอร์ดบอร์ด

172

สิ่งนี้ได้รับการจัดประเภทเป็น "งานตามที่ตั้งใจ" โดยวิศวกรของ Apple ฉันยื่นข้อผิดพลาดในขณะนี้กลับ เหตุผลของพวกเขาคือผู้ใช้มักจะป้อนข้อมูลในรูปแบบโมดอลดังนั้นพวกเขาจึงพยายามที่จะ "มีประโยชน์" และทำให้แป้นพิมพ์สามารถมองเห็นได้ซึ่งโดยปกติการเปลี่ยนแปลงต่างๆภายในมุมมองกิริยาอาจทำให้แป้นพิมพ์แสดง / ซ่อนซ้ำ ๆ

แก้ไข: นี่คือการตอบสนองของวิศวกร Apple ในฟอรัมนักพัฒนาซอฟต์แวร์:

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

นี่คือปัญหาที่ทำให้ผู้คนจำนวนมาก (รวมตัวเอง) แต่ในขณะนี้ดูเหมือนจะไม่มีวิธีการแก้ไข

UPDATE:

ใน iOS 4.3 และใหม่กว่าตอนนี้คุณสามารถใช้ `-disablesAutomaticKeyboardDismissal 'บนตัวควบคุมมุมมองของคุณเพื่อส่งคืน NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

วิธีนี้แก้ไขปัญหา


7
หยุดว้าวโอเค ขอบคุณมากสำหรับหัวขึ้น ประณาม Apple .. :(
Kalle

คุณส่งรายงานข้อผิดพลาดไปยัง Apple หรือไม่ ฉันได้ทำภายใต้ ID # 8384423 ฉันได้ส่งตัวอย่างแอปพลิเคชันเพื่อทำให้เกิดพฤติกรรมอีกครั้ง
Shaggy Frog

3
ในฐานะที่เป็นของ iOS 4.3 ตอนนี้มีวิธีการปิดใช้งานอัตโนมัติ KeyboardDismissal ซึ่งจะแก้ไขปัญหานี้ได้
Kalle

5
ฉันลองใช้วิธีปิดการใช้งานอัตโนมัติคีย์บอร์ด แต่ก็ยังไม่ได้แก้ปัญหาวิธีการแก้ปัญหา?
R. Dewi

3
@Snips: คุณต้องสร้างUINavigationControllerคลาสย่อยที่แทนที่disablesAutomaticKeyboardDismissalเพื่อส่งคืนNOและใช้สิ่งนี้เป็นตัวควบคุมการนำทางเมื่อคุณแสดงแผ่นงานแบบโมดอล ดูคำตอบจาก @ miha-hribar ด้านล่าง
ปาสกาล

149

UINavigationControllerโปรดระวังหากคุณกำลังแสดงกิริยาที่มี จากนั้นคุณต้องตั้งค่าdisablesAutomaticKeyboardDismissalบนตัวควบคุมทิศทางและไม่ได้อยู่ในตัวควบคุมมุมมอง คุณสามารถทำได้ด้วยหมวดหมู่

ไฟล์: UINavigationController + KeyboardDismiss.h

#import <Foundation/Foundation.h>

@interface UINavigationController (KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal;

@end

ไฟล์: UINavigationController + KeyboardDismiss.m

#import "UINavigationController+KeyboardDismiss.h"

@implementation UINavigationController(KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

@end

อย่าลืมนำเข้าหมวดหมู่ในไฟล์ที่คุณใช้ UINavigationController


19
1 ในที่สุดฉันเห็นชิ้นส่วนที่ขาดหายไปของข้อมูลสำหรับปัญหานี้ไฮไลต์: ว่าหนึ่งในความต้องการที่จะแทนที่disablesAutomaticKeyboardDismissalของUINavigationControllerไม่ควบคุมมุมมองของตัวเองเพื่อแก้ไขปัญหานี้
DarkDust

ดี! สิ่งที่ฉันต้องการ ขอบคุณ.
Justin

สมบูรณ์ ไม่ชัดเจนจากเอกสารอย่างเป็นทางการ แต่สมเหตุสมผลเนื่องจาก UINavigationController อยู่ในห่วงโซ่การตอบกลับ คำตอบที่ยอดเยี่ยม ขอบคุณ!
imnk

1
ฉันกำลังนำเสนอกล่องโต้ตอบโมดอลจาก UISplitViewController ฉันได้ลองใช้รหัสด้านบนแล้ว แต่แทนที่ UISplitViewController สำหรับ UINavigationController แต่ก็ยังใช้งานไม่ได้ วิธีนี้ควรใช้กับ UISplitViewController หรือไม่?
Snips

6
ไม่ใช่ความคิดที่ดีที่จะใช้วิธีการซ้ำในหมวดหมู่ คุณไม่สามารถมั่นใจได้ว่าการใช้งานแบบใดจะถูกเรียกดังนั้นที่ดีที่สุดคุณสามารถคาดหวังพฤติกรรมที่ไม่สอดคล้องกันได้ ดีกว่าที่จะสืบทอดจาก UINavigationController และแทนที่วิธีการในคลาสที่กำหนดเองของคุณ
sean woodward

51

ฉันแก้ไขสิ่งนี้โดยใช้UIModalPresentationPageSheetสไตล์การนำเสนอและปรับขนาดทันทีหลังจากฉันนำเสนอ ชอบมาก

viewController.modalPresentationStyle = UIModalPresentationPageSheet;
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewController animated:YES];
viewController.view.superview.autoresizingMask = 
    UIViewAutoresizingFlexibleTopMargin | 
    UIViewAutoresizingFlexibleBottomMargin;    
viewController.view.superview.frame = CGRectMake(
    viewController.view.superview.frame.origin.x,
    viewController.view.superview.frame.origin.y,
    540.0f,
    529.0f
);
viewController.view.superview.center = self.view.center;
[viewController release];

อืม ... มันไม่ถูกต้อง ... การปรับขนาดทำให้โมดอลวาดภาพตลก ... มันเหมือนกับว่ามันบีบเนื้อหาลงในกล่องขนาดใหม่หรืออะไรบางอย่าง ... ทุกอย่างดูตลก :(
toofah

นอกจากนี้ยังมีปัญหาการหมุนด้วยอันนี้ ... ถ้าคุณหมุนในขณะที่ modal นี้ขึ้นมันจะหด / ขยายราวกับว่ามันเป็นมุมมองแบบเต็มหน้า
toofah

2
ก่อนหน้านี้ฉันแก้ไขรหัสเพื่อจัดการกับปัญหาการหดตัว / การเติบโตเมื่อหมุน เพียงแค่ให้การกำกับดูแลกับขอบด้านบนและล่างที่ยืดหยุ่น ฉันไม่แน่ใจว่าฉันเห็นพฤติกรรมอื่น
azdev

1
สิ่งนี้จะทำงานได้ตราบใดที่คุณไม่ได้ผลักมุมมองอื่นที่ด้านบนของมุมมองนี้ เนื่องจากเมื่อคุณปิดมุมมองที่ถูกผลักให้อยู่เหนือมุมมองที่นำเสนอของ UIModalPresentationPageSheet มันกลับมาเป็นขนาดดั้งเดิม
V1ru8

มันได้ผล แต่คำในมุมมองดูเบลอเล็กน้อย ฉันไม่รู้ว่าทำไม
jeswang

1

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

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

@interface _TempUIVC : UIViewController
@end

@implementation _TempUIVC
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}
@end

@implementation UIViewController (Helpers)

- (void)_dismissModalViewController {
    [self dismissModalViewControllerAnimated:NO];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [self release];
}

- (void)forceKeyboardDismissUsingModalToggle:(BOOL)animated {
    [self retain];
    _TempUIVC *tuivc = [[_TempUIVC alloc] init];
    tuivc.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentModalViewController:tuivc animated:animated];
    if (animated) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_dismissModalViewController) name:UIKeyboardDidHideNotification object:nil];
    } else
        [self _dismissModalViewController];
    [tuivc release];
}

@end

ระวังด้วยสิ่งนี้แม้ว่าในขณะที่คุณดู DisAppear / viewDidDisappear และวิธีการเหล่านั้นทั้งหมดได้รับการเรียก อย่างที่ฉันบอกว่ามันไม่สวย แต่ทำงานได้

อดัม


1

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

อาจไม่ใช่วิธีที่ดีที่สุด แต่มันตรงไปตรงมามากและไม่ต้องการแฮ็กแฟนซีที่จะแตกด้วย iOS รุ่นใหญ่ครั้งต่อไป :)


1

ใส่รหัสนี้ใน viewWillDisappear ของคุณ: วิธีการควบคุมปัจจุบันเป็นอีกวิธีในการแก้ไขปัญหานี้:

Class UIKeyboardImpl = NSClassFromString(@"UIKeyboardImpl");
id activeInstance = [UIKeyboardImpl performSelector:@selector(activeInstance)];
[activeInstance performSelector:@selector(dismissKeyboard)];

1

ฉันพบว่าdisablesAutomaticKeyboardDismissalและการเพิ่มdisablesAutomaticKeyboardDismissalฟังก์ชั่นใช้งานไม่ได้สำหรับUITextFieldกล่องโต้ตอบโมดัล

แป้นพิมพ์บนหน้าจอจะไม่หายไป

โซลูชันของฉันคือปิดการใช้งานการควบคุมการป้อนข้อความทั้งหมดในกล่องโต้ตอบของฉันจากนั้นเปิดใช้งานส่วนที่เกี่ยวข้องได้ภายในเสี้ยววินาทีในภายหลัง

ดูเหมือนกับว่าเมื่อ iOS เห็นว่าไม่มีการUITextFieldควบคุมใด ๆ ที่เปิดใช้งานอยู่มันจะกำจัดคีย์บอร์ด


0

ฉันแน่ใจว่าคุณได้ดูสิ่งนี้แล้ว แต่คุณแน่ใจว่าคลาสคอนโทรลเลอร์ของคุณเชื่อมต่ออย่างถูกต้องในฐานะตัวแทน UITextField ใช่ไหม?


ฉันตั้งค่ามันด้วยตัวเองและวิธีการของผู้ได้รับมอบหมายนั้นก็ใช่แล้ว
Kalle

0

อาจไม่ส่งคืนไม่ได้ แต่ใช่ ดังนั้นมันสามารถหายไปได้

และคุณมีผลtextFieldShouldEndEditingตอบแทนใช่เช่นกัน?

และทำไมคุณถึงยิง[nextResponder becomeFirstResponder]! ขอโทษฉันเห็นตอนนี้

ฉันยังมีจำนวนของ UITextViews ที่ทุกคนมีคุณสมบัติ "แก้ไขได้" ของพวกเขาตั้งค่าเป็น FALSE

เราจะถือว่าไม่มีโอกาสใด ๆ ที่มีtagคุณค่าsecondField.tag+1หรือไม่? ถ้าเป็นเช่นนั้นคุณกำลังบอกพวกเขาให้ตอบกลับเป็นคนแรกแทนที่จะลาออกจากคำตอบแรก อาจจะใส่ NSLog () ลงไปในโครงสร้างนั้น


1
ไม่ = ไม่แทรกบรรทัดใหม่จากสิ่งที่ฉันสามารถบอกได้ และการตั้งค่าเป็นใช่ไม่ได้แก้ไข
Kalle

1
ฉันคิดว่า UITextField หนึ่งบรรทัดต่อหนึ่งบรรทัดไม่ได้ทำอะไรมากกับการขึ้นบรรทัดใหม่ ดังนั้นจึงเป็นเรื่องของการประมวลผลการกดปุ่ม Return / Done ตามที่ระบุในเอกสาร
mvds

คุณแน่ใจหรือไม่ว่าคุณติดทุกอย่างไว้ถูกต้อง? คุณใส่NSLog("tf %x / method ...",textField);ฟังก์ชั่นผู้ร่วมประชุมทั้งหมดหรือไม่?
mvds

ฟังก์ชั่นของผู้ได้รับมอบหมายนั้นถูกเรียกอย่างเหมาะสมและพวกเขาจะไม่ได้รับหากไม่ได้ตั้งค่าผู้ร่วมประชุมอย่างเหมาะสม และ NSLog ให้ EXC_BAD_ACCESS เตือนฉันด้วยว่ามันเป็นประเภทที่เข้ากันไม่ได้ใน XCode
Kalle

D'โอ้ ขออภัยฉันควรจะเห็นว่าตัวเอง ฉันได้อัปเดตคำตอบข้างต้นพร้อมกับผลลัพธ์ของ NSLogs เหล่านี้แล้วเนื่องจากการจัดรูปแบบจะทำให้เกิดปัญหาในการสื่อสาร ..
Kalle

0

สำหรับผู้ที่มีปัญหากับ UINavigationController ดูคำตอบของฉันสำหรับคำถามที่คล้ายกันที่นี่: https://stackoverflow.com/a/10507689/321785

แก้ไข: ฉันพิจารณาสิ่งนี้เป็นการปรับปรุงโซลูชันของ Miha Hribar (เนื่องจากการตัดสินใจเกิดขึ้นที่ที่ควร) และตรงข้ามกับความคิดเห็นของ Pascal เกี่ยวกับหมวดหมู่บน UIViewController


0

อาจไม่ใช่โซลูชันที่สมบูรณ์แบบ แต่ใช้งานได้
[self.view endEditing: YES];
ไม่ว่าจะใช้ปุ่มหรือท่าทางของคุณในที่ใดก็ตาม


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