Как я могу подключиться к методу действия для кнопки панели инструментов iPad? - PullRequest
3 голосов
/ 07 апреля 2010

Я использую шаблон разделенного представления, чтобы создать простое разделенное представление, которое, конечно, имеет всплывающее окно в портретном режиме. Я использую код по умолчанию, сгенерированный шаблоном, который добавляет / удаляет элемент панели инструментов, устанавливает контроллер поповер и удаляет его. Этими двумя методами являются splitViewController: willShowViewController: ... и splitViewController: willHideViewController: ...

Я пытаюсь выяснить, как заставить всплывающее окно исчезнуть, если пользователь нажимает кнопку панели инструментов во время отображения всплывающего окна. Вы можете сделать так, чтобы всплывающее окно исчезло без выбора элемента, если вы нажмете где-нибудь за пределами всплывающего окна, но я также хотел бы, чтобы оно исчезло, если пользователь снова нажмет кнопку.

В чем я застрял, так это в том, что не существует очевидного и простого способа подключиться к действию для кнопки панели инструментов. С помощью отладчика я могу сказать, что вызываемое на кнопке действие - это showMasterInPopover. И я новичок в работе с селекторами программно, я признаю.

Могу ли я как-нибудь написать действие и установить его на элемент панели инструментов, не отменяя действие, которое уже есть? например добавить действие, которое вызывает тот, который сейчас там? Или я должен был бы написать действие, которое показывает / скрывает поповер сам (поведение, которое выполняется за кулисами, предположительно, контроллером разделенного представления сейчас ???).

Или я упускаю простой способ добавить это поведение к этой кнопке без изменения существующего поведения, которое настраивается для меня?

Спасибо!

Ответы [ 6 ]

6 голосов
/ 24 апреля 2010

Получается, что вы можете заставить всплывающее окно отклонить при нажатии на barButtonItem путем реализации метода SplitViewController willPresentViewController следующим образом:

- (void) splitViewController:(UISplitViewController *)svc 
           popoverController: (UIPopoverController *)pc
   willPresentViewController: (UIViewController *)aViewController
{
    if (pc != nil) {
        [pc dismissPopoverAnimated:YES];
    }
}
1 голос
/ 15 апреля 2010

Таким образом, barButtonItem будет иметь UISplitViewController в качестве цели и showMasterInPopover: в качестве действия.Я не могу найти это в документации, поэтому я немного волнуюсь, что это неправильно, вызывать его, но я заставил его работать, изменив цель на self (контроллер представления) и действие на собственный метод, напримерэто:

- (void)showMasterInPopover:(id)sender {
    // ...insert custom stuff here...
    [splitViewController showMasterInPopover:sender];
}
0 голосов
/ 11 мая 2010

Может быть, вы все слишком усложняете это, или я прочитал что-то совсем другое, чем вы, ребята, хотели сделать ... но, возможно, это то, что вы все пытались понять так жестко:

-(void)togglePopOverController {

if ([popOverController isPopoverVisible]) {

[popOverController dismissPopoverAnimated:YES];

} else {

[popOverController presentPopoverFromBarButtonItem:bbiOpenPopOver permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

}

}
0 голосов
/ 17 апреля 2010

Ниже мое решение. Он начинается аналогично решению Greenisus, перехватывая обработчик событий кнопки панели инструментов UISplitViewController. Я использую флаг в своем контроллере, чтобы отслеживать, открыт ли поповер или нет. Наконец, для обработки случая, когда пользователь открывает всплывающее окно, а затем закрывает его, щелкая за пределами всплывающего окна, я реализую протокол UIPopoverControllerDelegate.

Во-первых, интерфейс контроллера:

@interface LaunchScene : NSObject <UISplitViewControllerDelegate, UIPopoverControllerDelegate>
{
    UISplitViewController* _splitViewController;    //Shows list UITableView on the left, and details on the right
    UIToolbar* _toolbar;                            //Toolbar for the button that will show the popover, when in portrait orientation
    SEL _svcAction;                                 //The action from the toolbar
    id _svcTarget;                                  //The target object from the toolbar
    UIPopoverController* _popover;                  //The popover that might need to be dismissed
    BOOL _popoverShowing;                           //Whether the popover is currently showing or not
}

-(void) svcToolbarClicked: (id)sender;

Я использую _svcAction и _svcTarget, чтобы устранить беспокойство Гринисуса о том, что он может не вызывать нужную функцию.

Ниже моя реализация. Для краткости я опустил код, который создает экземпляр UISplitViewController и подпредставлений. Отображается весь связанный с показом / скрытием код.

//the master view controller will be hidden so hook the popover
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc 
{   
    _popoverShowing = FALSE;
    if(_toolbar == nil) 
    {
        //set title of master button
        barButtonItem.title = @"Title goes here";

        //Impose my selector in between the SVController, and the SVController's default implementation
        _svcTarget = barButtonItem.target;
        _svcAction = barButtonItem.action;
        barButtonItem.target = self;
        barButtonItem.action = @selector(svcToolbarClicked:);

        //create a toolbar
        _toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 1024, 44)];
        [_toolbar setItems:[NSArray arrayWithObject:barButtonItem] animated:YES];
    }

    //add the toolbar to the details view (the second controller in the splitViewControllers array)
    UIViewController* temp = [_splitViewController.viewControllers objectAtIndex:1];
    [temp.view addSubview:_toolbar];
}

Вот моя функция, которая реагирует на щелчок панели инструментов. Это обрабатывает случай, когда пользователь нажимает и повторно нажимает кнопку панели инструментов.

-(void) svcToolbarClicked: (id)sender
{
    if(_popoverShowing)
    {
        [_popover dismissPopoverAnimated:TRUE];
    }
    else 
    {
        //Perform the default SVController implementation
        [_svcTarget performSelector:_svcAction];
    }
    //Toggle the flag
    _popoverShowing = !_popoverShowing;
}

Некоторые функции из UISplitViewControllerDelegate

//the master view (non-popover) will be shown again (meaning it is going to landscape orientation)
- (void)splitViewController:(UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)button 
{
    //remove the toolbar
    [_toolbar removeFromSuperview];
}

// the master view controller will be displayed in a popover (i.e. the button has been pressed, and the popover is about to be displayed.  
//Unfortunately triggers when the popover is ALREADY displayed.
- (void)splitViewController:(UISplitViewController*)svc popoverController:(UIPopoverController*)pc willPresentViewController:(UIViewController *)aViewController 
{   
    _popover = pc; //Grab the popover object  
    _popover.delegate = self;
}

Приведенного выше кода достаточно для большинства случаев. Однако если пользователь открывает всплывающее окно, а затем закрывает его, щелкая в другом месте экрана, логическое значение _popoverShowing будет содержать неверное значение, что заставит пользователя дважды нажать кнопку на панели инструментов, чтобы повторно открыть всплывающее окно. Чтобы исправить это, реализуйте метод UIPopoverControllerDelegate, как показано ниже.

//UIPopoverControllerDelegate method
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
    _popoverShowing = FALSE;
    _popover = nil;
}

Это заняло у меня целую вечность, чтобы разобраться, пролистывая документы и (я думаю) большинство вопросов UISplitViewController по StackOverflow. Я надеюсь, что кто-то найдет это полезным. Если это так, я желаю очки репутации. ; -)

0 голосов
/ 17 апреля 2010

Нет представителя, чтобы сделать реальный комментарий.: - (

@ Jann - Я почти уверен, что то, что хочет сделать Элизабет, довольно стандартно. Например, приложение Notes, которое поставляется с предварительно загруженной на iPad программой, закрывается и открывает всплывающее окно при нажатии на панель инструментовкнопка в левом верхнем углу.

0 голосов
/ 15 апреля 2010

Элизабет пишет:

Вы можете сделать так, чтобы всплывающее окно исчезло без выбора элемента, если вы нажмете где-нибудь за пределами всплывающего окна, но я также хотел бы, чтобы оно исчезло, если пользователь снова нажмет кнопку.

Прежде всего, позвольте мне сказать, что ни одно из того, что я собираюсь сказать, не должно восприниматься лично - это не так. Все это связано с годами разработки интерфейсов программирования и изучения Руководства по интерфейсу Apple для человека (а также наличия графического дизайнера, который постоянно пытается научить меня правильному способу выполнения задач). Это подразумевается как противоположная точка зрения, а не как напыщенная речь.

То, что вы предлагаете, является для меня проблемой пользовательского интерфейса и будет проблемой, которая вызывает проблемы, когда Apple рассматривает приложение. Никогда не предполагается, что объект с известным пользовательским интерфейсом выполняет функцию, которую он не выполняет нормально (например: кнопка never показывает , а затем освобождает представление / объект / окно . Переключатели делают это).

Например, увеличительное стекло на панели навигации означает «Поиск» (согласно определению Apple). В прошлом они и в будущем будут отказываться от приложений, которые используют это для масштабирования интерфейса. Например: Apple отклоняет ConvertBot или Одиссея: Тропа слез (найдите ее на странице). Язык отклонения всегда один и тот же (жирным шрифтом отмечены слова, которые они будут использовать для вашего использования):

«… нестандартным образом использует стандартные изображения экрана iPhone / iPod, что может привести к путанице среди пользователей. Изменение поведения стандартной графики iPhone, действий и изображений или имитация сбоев этих графиков, действий или изображений является нарушением соглашения о программе для разработчиков iPhone, которое требует от приложений соблюдения принципов интерфейса пользователя. «

Кроме того, если вы действительно хотите эту функцию, спросите себя: «Почему?». Если это потому, что вам самим это нравится, то я бы действительно пропустил это. Большинство пользователей будут смущены таким поведением и не будут его использовать, потому что они не будут знать, что это был вариант использования . Apple провела последние 3 года, обучая пользователей iPhoneOS тому, как использовать их ОС и элементы интерфейса. Последнее, что вы, как программист или дизайнер, хотите сделать, это потратить время на то, чтобы обучить пользователя тому, как использовать ваше приложение. Как правило, они удаляют ваше приложение со своего устройства и переходят к другому аналогичному приложению, вместо того чтобы заставлять себя изучать ваш способ ведения дел.

Только мои $ .02

...