Странное поведение кнопки отмены 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]]:;

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


ИДЕАЛЬНЫЙ! Спасибо. Это правильное решение для меня, так как у меня была эта проблема с 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];

5

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

    [actionSheet showFromTabBar:self.tabBarController.tabBar];

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


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

1

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

UIViewController *parentView = [[self parentViewController] parentViewController];
[docController presentOptionsMenuFromRect: rect inView: parentView.view animated:YES];

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.