Modal ViewController sunum stili UIModalPresentationFormSheet ise iPad klavye çalışmaz


214

Not:

İOS 4.3'ten itibaren çözüm için kabul edilen cevaba (en çok oylananlardan biri değil) bakın.

Bu soru , iPad klavyesinde bulunan ve bir gezinme denetleyicisiyle kalıcı bir iletişim kutusunda gösterildiğinde reddedilmeyi reddettiği bir davranışla ilgilidir.

Temel olarak, navigasyon kontrol cihazını aşağıdaki satırla aşağıdaki gibi sunarsam:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

Klavye reddedilmeyi reddediyor. Bu çizgiye yorum yaparsam, klavye iyi gider.

...

İki textField'im var, kullanıcı adı ve şifre; kullanıcı adında bir İleri düğmesi ve parolanın Bitti düğmesi vardır. Bunu bir modsal gezinme denetleyicisinde sunarsam klavye kaybolmaz.

İŞLER

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

ÇALIŞMIYOR

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

Gezinti denetleyici parçasını çıkarırsam ve kendi başına modal görünüm denetleyicisi olarak 'b' değerini sunarsam çalışır. Gezinti denetleyicisi sorun mu var?

İŞLER

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

İŞLER

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

Aşağıdaki SO sorusu aynı soruna sahip gibi görünüyor, ancak cevap yok: stackoverflow.com/questions/3019709/…
Kalle

+1 Harika açıklamanız için teşekkür ederiz. Ama bu yöntemi nereye koymam gerekiyor? Model denetleyicisini sunmak için kod oluşturduğum yerde çalışmıyor ...
Lorenzo B

1
Kalıcı görünüm denetleyicisi sınıfında olmalıdır.
Kalle

Teşekkürler. Anlıyorum. UINavigationControllerSınıf için bir kategoriye koyarak çözdüm . Şerefe.
Lorenzo B

Bu soru için sana çok borçluyum. resignFirstResponderÇalıştırmasına şaşırdım ama klavye hala gösteriliyor. Senaryom (navig contrllr ile PresentationFormSheet) tam olarak sizinkiyle aynı. Bir ton teşekkürler !!
sErVerdevIL

Yanıtlar:


115

Modsal olarak sunulan görünüm denetleyicisinde, disablesAutomaticKeyboardDismissalgeri dönmek için geçersiz kılın NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

Evet, 4.3'ten beri durum böyle görünüyor. Soruyu güncelleyecek. Teşekkürler!
Kalle

2
Bunun navigasyon kontrolörüne eklenmesi gerekir
pottedmeat

1
Evet, üzerine yazdığınızda çalışır. Benim için gerçekten işe yarayan tek şey bu.
James Laurenstin

Hayat kurtarıcı! Apple neden böyle şeyler yapıyor? Şüphesiz, HAYIR olarak varsayılan olmalı ve gerçekten istiyorsak değiştirmemize izin
vermeliyiz

UIViewController türevi sınıfta çalışmıyor, devre dışı
bırakılıyorOtomatikKeyboardDismissal

172

Bu, Apple mühendisleri tarafından "amaçlandığı gibi çalışır" olarak sınıflandırılmıştır. Bir süre önce bunun için bir hata dosyaladım. Onların akıl yürütmesi, kullanıcının genellikle modsal bir biçimde veri gireceğidir, bu nedenle "yardımcı" olmaya çalışırlar ve modsal görünümdeki çeşitli geçişlerin klavyenin tekrar tekrar gösterilmesine / gizlenmesine neden olabileceği yerlerde klavyeyi görünür tutarlar.

edit: İşte bir Apple mühendisi geliştirici forumlarında yanıt :

Görünümünüz UIModalPresentationFormSheet stiliyle şans eseri sunuldu mu? Sık sık giriş ve çıkış animasyonlarından kaçınmak için, ilk yanıtlayıcı olmasa bile klavye bazen ekranda kalır. Bu bir hata değil.

Bu, birçok insana (kendim dahil) problemler veriyor, ancak şu anda bunun üzerinde çalışmanın bir yolu yok gibi görünüyor.

GÜNCELLEME:

İOS 4.3 ve sonraki sürümlerde artık NO döndürmek için görünüm denetleyicinize `-disablesAutomaticKeyboardDismissal 'uygulayabilirsiniz:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

Bu sorunu düzeltir.


7
duraklama Wow, tamam. Head up için çok teşekkürler. Lanet Elma .. :(
Kalle

Apple'a bir hata raporu gönderdiniz mi? 8384423 ID altında bunu yaptım. Ayrıca davranışı yeniden oluşturmak için örnek bir başvuru gönderdik.
Shaggy Frog

3
İOS 4.3'ten itibaren artık bu sorunu çözen bir devre dışı bırakmaOtomatikKeyboardDismissal yöntemi var.
Kalle

5
OtomatikKeyboardDismissal yöntemi devre dışı bırakmaya çalışıyorum, ama yine de sorunu çözmedi, nasıl çözülür?
R. Dewi

3
@Snips: Geri dönmek UINavigationControlleriçin geçersiz kılan bir alt sınıf oluşturmanız ve bunu kalıcı bir form sayfası sunduğunuzda gezinti denetleyicisi olarak kullanmanız gerekir. Aşağıdaki @ miha-hribar'ın cevabına bakınız. disablesAutomaticKeyboardDismissalNO
Pascal

149

Kipli a ile görüntülüyorsanız dikkatli olun UINavigationController. Ardından disablesAutomaticKeyboardDismissal, görünüm denetleyicisine değil, gezinti denetleyicisine ayarlamanız gerekir . Bunu kategorilerle kolayca yapabilirsiniz.

Dosya: UINavigationController + KeyboardDismiss.h

#import <Foundation/Foundation.h>

@interface UINavigationController (KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal;

@end

Dosya: UINavigationController + KeyboardDismiss.m

#import "UINavigationController+KeyboardDismiss.h"

@implementation UINavigationController(KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

@end

UINavigationController'ı kullandığınız dosyadaki kategoriyi içe aktarmayı unutmayın.


19
1, son olarak vurgulanan Bu sorunla ilgili bilgilerin eksik parçasını bakın: bir ihtiyacı geçersiz kılmak için bu disablesAutomaticKeyboardDismissalbir UINavigationControllerbu sorunu gidermek için değil, kendi bakış denetleyicisi.
DarkDust

Güzel! Tam ihtiyacım olan şey. Teşekkür ederim.
Justin

Mükemmel. Resmi dokümanlardan net değil ancak UINavigationController'ın yanıtlayıcı zincirinde olması nedeniyle mantıklı. Mükemmel cevap. Teşekkür ederim!
imnk

1
Bir UISplitViewController kalıcı mod iletişim sunuyorum. Yukarıdaki kodu denedim, ama UINavigationController yerine UISplitViewController yerine, ama yine de çalışmıyor. Bu yöntem bir UISplitViewController üzerinde de çalışmalı mıdır?
Snips

6
Bir kategoride yinelenen bir yöntem uygulamak iyi bir fikir değildir. Hangi uygulamanın çağrılacağından asla emin olamazsınız, bu yüzden en iyi ihtimalle tutarsız davranış bekleyebilirsiniz. UINavigationController öğesinden devralmak ve özel sınıfınızdaki yöntemi geçersiz kılmak daha iyidir.
sean woodward

51

Bunu UIModalPresentationPageSheetsunum stilini kullanarak ve sunumdan hemen sonra yeniden boyutlandırarak çözdüm. Şöyle ki:

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

Hmmm ... bu doğru değil ... yeniden boyutlandırma, modalın komik resim yapmasına neden oluyor ... sanki içeriği yeni boyut kutusuna sığacak şekilde eziyor gibi ... her şey komik görünüyor. :(
toofah

Bununla ilgili rotasyon problemleri de var ... bu
moddayken döndürürseniz

2
toofah, dönerken küçülen / büyüyen sorunla başa çıkmak için kodu düzenledim; sadece denetime esnek bir üst ve alt kenar boşluğu verme meselesi. Diğer davranışı gördüğümden emin değilim.
azdev

1
bu, yalnızca başka bir görünümün üzerine çıkmadığınız sürece işe yarar. Çünkü UIModalPresentationPageSheet sunulan görünümün üzerine itilen görünümü kapattığınızda, orijinal boyutuna geri döner.
V1ru8

İşe yaradı. Ancak görünümdeki kelime biraz bulanık görünüyor. Nedenini bilmiyorum.
jeswang

1

Farklı bir modal ekranı değiştirirseniz klavyenin kaybolmasını sağlayabilirsiniz. Güzel değil ve aşağı canlanmıyor, ama gitmesini sağlayabilirsiniz.

Bir düzeltme olsaydı harika olurdu, ama şimdilik bu işe yarıyor. Bir kategoride kamalayabilir UIViewControllerve klavyenin gitmesini istediğinizde arayabilirsiniz:

@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

ViewDidAppear / viewDidDisappear ve tüm bu yöntemler çağrılırken buna rağmen dikkatli olun. Dediğim gibi, hoş değil, ama işe yarıyor.

-Adam


1

Ayrıca, deyimi kontrol ederek evrensel bir uygulamada da bu sorunu çözebilirsiniz ve bir iPad ise, klavyeyi otomatik olarak açmayın ve kullanıcının düzenlemek istediklerine dokunmasına izin vermeyin.

En güzel çözüm olmayabilir, ancak çok basittir ve bir sonraki büyük iOS sürümüyle kırılacak herhangi bir fantezi hackine ihtiyaç duymaz :)


1

Bu kodu viewWillDisappear: akım denetleyicisinin yöntemi bunu düzeltmenin başka bir yoludur:

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

1

Bunu buldum disablesAutomaticKeyboardDismissalve bir disablesAutomaticKeyboardDismissalişlev eklemek benim için işe yaramadıUITextField için kalıcı bir iletişim kutusu içinde .

Ekran klavyesi gitmez.

Çözümüm devre dışı bırakmaktı iletişim kutusundaki tüm metin giriş denetimlerini , ardından ilgili olanları bir saniye sonra yeniden etkinleştirmekti.

İOS hiçbirinin gördüğünde sanki görünüyor UITextFieldkontroller etkindir, o zaman gelmez klavyenin kurtulmak.


0

Buna baktığınızdan eminim, ancak denetleyici sınıfınızın UITextField delegesi olarak düzgün bağlandığından eminsiniz, değil mi?


Kendim manuel olarak ayarladım ve delege yöntemleri çağrıldı, yani evet.
Kalle

0

belki HAYIR dönmeyin, EVET. Böylece gidebilir.

Ve textFieldShouldEndEditinggeri dönen bir EVETiniz var mı?

Ve neden sen ateş ediyorlar [nextResponder becomeFirstResponder]?! üzgünüm şimdi görüyorum

Ayrıca hepsi "düzenlenebilir" özelliği YANLIŞ olarak ayarlanmış UITextViews bir dizi var.

Hiçbirinin, hiçbir şekilde, bir tagdeğeri olmadığını varsayabilir miyiz secondField.tag+1? Eğer öyleyse, onlara ilk cevaplayıcıyı istifa etmek yerine ilk cevaplayıcı olmalarını söylüyorsunuz. Belki de yapının içine bazı NSLog () koyun.


1
NO = söyleyebileceğimden satırsonu eklemeyin. Ve EVET olarak ayarlamak sorunu çözmedi.
Kalle

1
Bir UITextField, tanımı gereği bir satır olmak, yeni satırlarla pek bir şey yapmaz diye düşünüyorum. Bu nedenle, dokümanlarda belirtildiği gibi, İade / Tamamlandı düğmesine basılmasıyla ilgili işlem daha fazladır.
mvds

Her şeyi doğru şekilde bağladığınızdan emin misiniz? Bir koyduk NSLog("tf %x / method ...",textField);tüm delege fonksiyonlarda?
mvds

Delege işlevleri uygun şekilde çağrılır ve delege uygun şekilde kurulmamışsa böyle olmaz. Ve NSLog bir EXC_BAD_ACCESS verir. Ayrıca beni XCode'da uyumsuz tipte olduğu konusunda uyarıyor.
Kalle

D'oh. Üzgünüm, bunu kendim görmeliydim. Biçimlendirme işleminde kendini göstereceğinden, yukarıdaki yanıtı bu NSLogs'un sonuçlarıyla güncelledim ..
Kalle

0

UINavigationController ile sorun yaşayanlar için benzer bir soruya cevabımı burada bulabilirsiniz: https://stackoverflow.com/a/10507689/321785

Düzenleme: Bu Miha Hribar'ın çözümü için bir gelişme (karar olması gerektiği yerde gerçekleştiği için) ve Pascal'ın UIViewController'daki bir kategori ile ilgili yorumunun aksine


0

mükemmel bir çözüm olmayabilir, ancak çalışır
[self.view endEditing: YES];
düğmenizin veya hareketinizin nereden uygulandığı


0
Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.