Клавіатура iPad не відхилить, якщо модальний стиль подання ViewController є UIModalPresentationFormSheet


214

Примітка:

Див. Прийняту відповідь (не голосуючий) для вирішення станом на iOS 4.3.

Це питання стосується поведінки, виявленої на клавіатурі iPad, де вона відмовляється відмовлятися, якщо відображається в модальному діалозі з контролером навігації.

В основному, якщо я представляю контролеру навігації наступний рядок, як показано нижче:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

Клавіатура відмовляється від відхилення. Якщо я коментую цей рядок, клавіатура прекрасно проходить.

...

У мене є два текстових поля, ім’я користувача та пароль; ім'я користувача має кнопку Далі, а пароль має кнопку Готово. Клавіатура не зникне, якщо я представлю це в модальному контролері навігації.

РОБОТИ

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' як контролер модального перегляду сам по собі, він працює. Чи проблема в навігаційному контролері?

РОБОТИ

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

РОБОТИ

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

Таке запитання ТА, схоже, має таку ж проблему, але відповіді немає: stackoverflow.com/questions/3019709/…
Kalle

+1 Дякую за чудове пояснення. Але де я маю поставити цей метод? Здається, не працює, де я створюю код для представлення контролера моделі ...
Lorenzo B

1
Він повинен бути у самому класі контролера модального перегляду.
Калле

Дякую. Я бачу. Я вирішив поставити його в категорію для UINavigationControllerкласу. Ура.
Лоренцо Б

Я так вам вдячний за це питання. Я був здивований тим, що resignFirstResponderвиконується, але клавіатура все ще показується. Мій сценарій (презентаціяFormSheet з навігацією contrllr) точно такий же, як і ваш. Дякую тони !!
sErVerdevIL

Відповіді:


115

У контролері подання, який представлений модально, просто перемістіть disablesAutomaticKeyboardDismissalдля повернення NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

Так, так як 4.3, мабуть, так і є. Буде оновлено питання. Дякую!
Kalle

2
Це потрібно додати до контролера навігації
м'ясо в горщиках

1
Так, працює, коли ви перезаписали його в NavigationController. Це єдине, що насправді працювало на мене.
Джеймс Лоренстін

Рятувальник життя! Чому Apple робить такі речі? Безумовно, воно повинно бути за замовчуванням НІ і дозволити нам змінити це, якщо ми дійсно хочемо
SomaMan

Не працює над похідним класом UIViewController, відключаєАвтоматична
клавіатура. Звільнення

172

Інженери Apple віднесли це до "роботи за призначенням". Я відправив помилку на це на деякий час назад. Їх міркування полягають у тому, що користувач часто збирається вводити дані в модальній формі, тому вони намагаються бути "корисними" і зберігати клавіатуру видимою там, де зазвичай різні переходи в модальному режимі можуть спричиняти / ховати клавіатуру неодноразово.

редагувати: ось відповідь інженера Apple на форумах розробників:

Чи був ваш погляд випадково представлений у стилі UIModalPresentationFormSheet? Щоб уникнути частих анімаційних переходів, клавіатура іноді залишатиметься на екрані, навіть коли немає першого відповіді. Це не помилка.

Це доставляє багатьом проблемам (включаючи і мене), але наразі, мабуть, немає способу обійти це.

ОНОВЛЕННЯ:

У iOS 4.3 та новіших версіях тепер ви можете реалізувати `-disablesAutomaticKeyboardDismissal 'на своєму контролері перегляду, щоб повернути НІ:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

Це вирішує проблему.


7
пауза Вау, добре. Дякую за голову вгору. Чорт Яблу .. :(
Kalle

Ви подали звіт про помилку в Apple? Я зробив це під ідентифікатором № 8384423. Я також подав зразок заяви для відтворення поведінки.
Shaggy Frog

3
Станом на iOS 4.3 тепер існує метод disablesAutomaticKeyboardDismissal, який вирішує цю проблему.
Калле

5
Я намагаюся, що цей метод onesposobljavaAutomaticKeyboardDismissation, але це все ще не вирішило проблему, як її вирішити?
Р. Деві

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

Приємно! Тільки те, що мені було потрібно. Дякую.
Джастін

Ідеально. Не зрозуміло з офіційних документів, але це має сенс через те, що UINavigationController знаходиться в ланцюжку відповідей. Відмінна відповідь. Дякую!
imnk

1
Я представляю модальний діалог від UISplitViewController. Я спробував вищевказаний код, але замінив UISplitViewController на UINavigationController, але він все ще не працює. Чи повинен цей метод також працювати на UISplitViewController?
Сніпи

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

У цьому також є проблеми з обертанням ... якщо ви обертаєтесь, поки цей модальний режим вгору, він зменшиться / зросте так, ніби це був повний перегляд сторінки
toofah

2
toofah, я редагував код, щоб вирішити проблему скорочення / зростаючої при обертанні; лише питання надання нагляду гнучкому верхньому та нижньому запасам. Я не впевнений, що бачу іншу поведінку.
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

Будьте обережні з цим, хоча ви переглядаєтеDidAppear / 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 () в цю структуру if.


1
НІ = не вставляйте новий рядок, з того, що я можу сказати. І встановити його ТАК, це не виправили.
Калле

1
Я вважаю, що UITextField, будучи одним рядком за визначенням, не дуже сильно відповідає новим рядкам. Тож мова йде більше про обробку натискання кнопки Повернення / Готово, як зазначено в документах.
mvds

Ви дуже впевнені, що підключили все правильно? Ви помістили NSLog("tf %x / method ...",textField);всі функції делегування?
mvds

Ну, функції делегата викликаються належним чином, і їх не було б, якби делегат не був налаштований належним чином. І NSLog дає EXC_BAD_ACCESS. Також попереджає мене про те, що він є несумісним типом у XCode.
Kalle

D'oh. Вибачте, я повинен був це бачити сам. Я оновив відповідь вище з результатами цих NSLogs, оскільки форматування вийде в комунікації ..
Kalle,

0

Для тих, хто має проблеми з UINavigationController, дивіться мою відповідь на подібне запитання тут: https://stackoverflow.com/a/10507689/321785

Редагувати: Я вважаю це вдосконаленням рішення Міха Хрібара (оскільки рішення приймається там, де воно повинно), і на відміну від коментаря Паскаля щодо категорії UIViewController


0

може бути не ідеальним рішенням, але працює
[self.view endEditing: YES];
звідки б не було застосовано вашу кнопку або жест, щоб подати модальний режим


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.