Странное поведение кнопки отмены UIActionSheet

116

У меня есть UIBarButtonItem, открывающий лист действий, чтобы предложить пользователям выбор того, что им делать. Все работает должным образом, если я не пытаюсь нажать кнопку «Отмена». Похоже, что цель кнопки переместилась вверх от того места, где должна быть. Я могу активировать его, только нажав где-нибудь посередине кнопок «Отмена» и «ОК».

Я пробовал использовать листы действий в других приложениях, и они работают нормально, так что это не просто мой большой палец. Лист действий открывается в UIViewController

- (void)showOpenOptions
{
    UIActionSheet *sheet = [[UIActionSheet alloc] 
    initWithTitle:NSLocalizedString(@"Open link in external application?", @"Open in external application")
    delegate:self
    cancelButtonTitle:NSLocalizedString(@"Cancel", @"Cancel")
    destructiveButtonTitle:NSLocalizedString(@"Open Link", @"Open Link")
    otherButtonTitles:nil];

    [sheet showInView:self.view];
    [sheet release];
}
Неванский король
источник
5
Кстати, на WWDC во время сеанса обзора пользовательского интерфейса Apple мне сказали, что красная кнопка на листах действий действительно предназначена для «деструктивных» действий (например, «удалить»).
Рамин
Да, я недавно прочитал руководство по человеческому интерфейсу и увидел это. Поменял его с красного на серый.
Nevan King

Ответы:

190

Вместо того, чтобы передавать представление текущего контроллера представления в лист действий, используйте showFromTabBar:метод UIActionSheet.

Правильный путь
Это даст правильную область касания:

[actionSheet showFromTabBar:self.tabBarController.tabBar];

Неправильный способ
Это приведет к тому, что область нажатия окажется не в том месте (если вы используете панель вкладок или панель инструментов):

[actionSheet showInView:self.view];

Если вы используете панель инструментов , используйте showFromToolbar:вместо этого метод. Вам понадобится ссылка на панель инструментов, скорее всего, ivar

[actionSheet showFromToolbar:self.myToolbar];

Мой старый ответ тоже работает, но взломан:

Только что нашел возможный ответ:

01 декабря 2008 г. 22:22 Том Сакстон: Я еще раз посмотрел на эту ошибку, и, похоже, это проблема с панелью вкладок.

Если вы вызываете [sheet showInView: self.view] UIActionSheet из контроллера представления, который является дочерним элементом UITabViewController, то проверка нажатия на кнопке отмены не выполняется в той части UIActionSheet, которая находится над представлением панели вкладок.

Если вместо этого вы передадите представление UITabBarController, то UIActionSheet будет действовать так, как ожидалось.

ПРИМЕЧАНИЕ: в iPhone OS 2.1 и более ранних версиях UIActionSheet появлялся из верхней части панели вкладок при переходе к дочернему представлению, но в 2.2 он поднимался снизу панели вкладок и, таким образом, перекрывал представление вкладок.

http://openradar.appspot.com/6410780

Изменить: он работает правильно, когда я меняю вид на вид панели вкладок

[sheet showInView:self.parentViewController.tabBarController.view];
Неванский король
источник
Проголосовали за это, потому что это работает. Почему это лучше, чем другие ответы?
Бентфорд
1
Почему parentViewController? Даже если представление находится на вкладке просмотра навигации, BarController все равно должен указывать в нужное место. У меня работает без parentViewController в любом случае.
Натан
11
Другой ответ кажется потенциально лучше. Найдите [actionSheet showInView: [окно self.view]]. Кажется более простым и более общим.
Кевин
Большое спасибо за публикацию этого ответа.
fulvio
1
В моем приложении нет панели вкладок, но проблема все еще есть. Я решил это с помощью '[serf.view window]'. В любом случае это не проблема с панелью вкладок.
Майк Кескинов,
37

Я нашел ответ в течение здесь , что работает.

используя [filterActionSheet showInView:[self.view window]]:;

Я попробовал несколько способов добраться до панели вкладок, и, как это приложение настроено, кажется запутанным ...

driveguy
источник
ИДЕАЛЬНЫЙ! Спасибо. Это правильное решение для меня, так как у меня была эта проблема с UITableViewController, у которого была панель инструментов, а не TabBar, как у других здесь.
Уильям Деннисс,
хороший материал, у меня это сработало! это определенно самый простой способ сделать это!
cgossain 07
2
Это вызывает другую проблему. ActionSheet отображается в портретной ориентации, когда устройство находится в альбомной ориентации (как и все другое содержимое).
Майк Кескинов
22

Вместо этого используйте:

[sheet showFromTabBar:theTabBar];
Кори Флойд
источник
1
Я исправил это с showInTabBar:на showFromTabBar:. Также обратите внимание, что есть метод showFromToolbar: в зависимости от того, какая экранная мебель у вас внизу экрана. Я думаю, что это лучший ответ, чем принятый ответ.
Стивен Дарлингтон,
Стивен, интересно, почему вы думаете, что это лучше, чем указывать showInView: theTabBar? С точки зрения сопряжения я бы подумал, что showInView, вероятно, было бы более идеальным, в случае, если позже tabBar будет удален, например, заменен панелью инструментов. Я бы подумал, что конкретному контроллеру подвидов на самом деле не нужно знать или заботиться.
Билли Грей,
Если панель вкладок будет удалена позже, вам придется отредактировать эту строку кода независимо (если, возможно, theTabBar не является ссылкой с плохим именем на переданное представление). Поэтому я не понимаю, как этот метод связан больше, чем showInView: theTabBar. Я также использую showFromTabBar:, так как мне это кажется более безопасным. Я не знаю, что происходит внутри, но я полагаю, что showFromTabBar: с меньшей вероятностью сломается в будущих выпусках ОС, чем showFromView: с представлением панели вкладок.
Кристофер Пикслей,
10

Вот исправление. Попробуйте это:

[actionsheet showInView:[UIApplication sharedApplication].keyWindow];
Viggnesh
источник
5

Я думаю, что сочетание трех ответов - правильный способ справиться с этим:

    [actionSheet showFromTabBar:self.tabBarController.tabBar];

то есть используйте showFromTabBar (вот почему он существует), и вам не нужен parentViewController, как указал Натан (фактически, self.parentViewController.tabBarController.tabBar возвращает для меня nil.

RawMean
источник
Конечно, он возвращает nil, потому что родительский контроллер представления (которым является UITabBarViewController) не вложен в другой UITabBarController, поэтому его свойство tabBarController равно нулю.
Dominik Seibold
1

FYI - была та же проблема с таблицей действий UIDocumentInteractionController, наступающей на панель вкладок. Для исправления использовал следующее.

UIViewController *parentView = [[self parentViewController] parentViewController];
[docController presentOptionsMenuFromRect: rect inView: parentView.view animated:YES];
Микки
источник
-2

писать упрощенный код

 actionSheet.actionSheetStyle = UIActionSheetStyleDefault;

это отлично работает

джайеш каватия
источник