Como faço para conectar o método de ação para um botão da barra de ferramentas do iPad Popover?
-
24-09-2019 - |
Pergunta
Estou usando o modelo de exibição dividida para criar uma visão simples de divisão que, é claro, um popover no modo retrato. Estou usando o código padrão gerado pelo modelo que adiciona/remove o item da barra de ferramentas e define o controlador de popover e o remove. Esses dois métodos são SplitViewController: WillSowViewController: ... e SplitViewController: WillHideViewController: ...
Estou tentando descobrir como fazer o popover desaparecer se o usuário tocar no botão da barra de ferramentas enquanto o popover for exibido. Você pode fazer com que o popover desapareça sem selecionar um item se você tocar em qualquer lugar fora do popover, mas eu também gostaria de fazê -lo desaparecer se o usuário tocar o botão novamente.
Onde estou preso é o seguinte: não parece haver uma maneira óbvia e fácil de conectar -se à ação do botão da barra de ferramentas. Posso dizer, usando o depurador, que a ação que está sendo chamada no botão é o showmasterInpopover. E sou novo em trabalhar com seletores programaticamente, admito.
De alguma forma, posso escrever uma ação e defini -la no item da barra de ferramentas sem substituir a ação que já está lá? Por exemplo, adicione uma ação que chama a que está lá agora? Ou eu teria que escrever uma ação que mostre/esconde o popover (comportamento que está sendo feito nos bastidores presumivelmente pelo controlador de visão dividida agora ???).
Ou estou perdendo uma maneira fácil de adicionar esse comportamento a este botão sem alterar o comportamento existente que está sendo configurado para mim?
Obrigada!
Solução
Acontece que você pode fazer com que o popover descarte ao clicar no barbuttonitem implementando o método SplitViewController WillPresentViewController da seguinte maneira:
- (void) splitViewController:(UISplitViewController *)svc
popoverController: (UIPopoverController *)pc
willPresentViewController: (UIViewController *)aViewController
{
if (pc != nil) {
[pc dismissPopoverAnimated:YES];
}
}
Outras dicas
Portanto, o BarbuttonItem terá o UISPLITVIELCONTROLLER como alvo e showmasterInpopover: como a ação. Não consigo encontrá -lo na documentação, por isso estou um pouco preocupado que não seja bom chamá -lo, mas consegui funcionar alterando o alvo para si (o controlador de exibição) e a ação para um método personalizado, como isto:
- (void)showMasterInPopover:(id)sender {
// ...insert custom stuff here...
[splitViewController showMasterInPopover:sender];
}
Não tenha o representante para fazer um comentário real. :-(
@Jann - Tenho certeza de que o que Elizabeth quer fazer é bastante padrão. Por exemplo, o aplicativo Notas que os navios pré-carregados no iPad fecham e abre o popover quando você pressiona o botão da barra de ferramentas no canto superior esquerdo.
Abaixo está minha solução. Começa semelhante à solução de Greenisus, conectando o UISplitViewController
Manipulador de eventos da barra de ferramentas da barra de ferramentas. Eu uso um sinalizador no meu controlador para rastrear se o popover está aberto ou não. Finalmente, para lidar com o caso em que o usuário abre o popover, depois o fecha clicando fora do popover, implemento o UIPopoverControllerDelegate
protocolo.
Primeiro, a interface do controlador:
@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;
Eu uso _svcaction e _svcTarget para addess Greenisus se preocupar de que ele pode não estar chamando a função certa.
Abaixo está minha implementação. Para a brevidade, omiti o código que instancia o UisplitViewController e as subviews. Todo o código relacionado ao show/oculto é mostrado.
//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];
}
Aqui está minha função, que responde ao clique da barra de ferramentas. Isso lida com o caso em que o usuário toca e re-toca o botão da barra de ferramentas.
-(void) svcToolbarClicked: (id)sender
{
if(_popoverShowing)
{
[_popover dismissPopoverAnimated:TRUE];
}
else
{
//Perform the default SVController implementation
[_svcTarget performSelector:_svcAction];
}
//Toggle the flag
_popoverShowing = !_popoverShowing;
}
Algumas funções do 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;
}
O código acima é suficiente para a maioria dos casos. No entanto, se o usuário abrir o popover, então descarta clicando em outras partes da tela, o _popoverShowing
O Boolean conterá um valor incorreto, que forçará o usuário a tocar no botão da barra de ferramentas duas vezes para reabrir o popover. Para consertar isso, implemente o UIPopoverControllerDelegate
Método, como o trecho abaixo.
//UIPopoverControllerDelegate method
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
_popoverShowing = FALSE;
_popover = nil;
}
Isso levou uma eternidade para descobrir, cavando os documentos e (acho) a maioria das perguntas do UISPLITVIEWController no StackOverflow. Espero que alguém ache isso útil. Nesse caso, cobiço pontos de reputação. ;-)
Talvez todos vocês apenas compliquem demais ou eu já li algo muito diferente do que vocês queriam fazer ... mas talvez seja isso que todos vocês estavam tentando descobrir tanto:
-(void)togglePopOverController {
if ([popOverController isPopoverVisible]) {
[popOverController dismissPopoverAnimated:YES];
} else {
[popOverController presentPopoverFromBarButtonItem:bbiOpenPopOver permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
Elisabeth escreve:
Você pode fazer com que o popover desapareça sem selecionar um item se você tocar em qualquer lugar fora do popover, mas eu também gostaria de fazê -lo desaparecer se o usuário tocar o botão novamente.
Primeiro de tudo, deixe -me dizer que nada do que estou prestes a dizer é ser tomado para o lado pessoal - isso não se entende dessa maneira. Tudo vem de anos de projetar interfaces de programação e estudar as diretrizes da interface humana da Apple (além de ter um designer gráfico que é contínuo tentando para me ensinar a maneira certa de fazer as coisas). É um ponto de vista oposto e não como um discurso retórico.
O que você está sugerindo é um problema em termos de interface do usuário para mim e será um problema que causa problemas quando a Apple revisar o aplicativo. Você nunca deve ter um objeto conhecido que ele execute uma função que ele não execute normalmente (por exemplo: um botão Nunca shows e depois libera uma visualização/objeto/janela. TOGLES FAÇA ISSO).
Por exemplo, uma lupa na barra de marinho significa pesquisa (conforme definido pela Apple). Eles têm no passado e continuarão no futuro para recusar aplicativos que o usam para ampliar a interface. Por exemplo: Apple rejeita o convertbot ou A Odisséia: Trilha das Lágrimas (pesquise na página). O idioma na rejeição é sempre o mesmo (marcando em negrito o que eles citariam para o seu uso):
“... usa imagens padrão de tela iPhone/iPod de maneira não padrão, potencialmente resultando em confusão do usuário. Alterando o comportamento dos gráficos padrão do iPhone, ações, e imagens, ou simular falhas desses gráficos, ações ou imagens, é uma violação do contrato do Programa de Desenvolveres para iPhone, que exige que os aplicativos cumpram as diretrizes da interface humana. ”
Além disso, se você realmente quer esse recurso, pergunte a si mesmo: "Por quê?". Se for porque você, você mesmo, eu realmente pularia. A maioria dos usuários ficaria confusa com esse comportamento e não o usaria porque Eles não sabiam que era uma opção usar. A Apple passou os últimos 3 anos treinando os usuários do iPhoneos como usar seus elementos de sistema operacional e interface. A última coisa que você, como programador ou designer, deseja fazer é gastar tempo tentando treinar um usuário sobre como usar seu aplicativo. Eles geralmente removem seu aplicativo do dispositivo e se movem para outro aplicativo semelhante, em vez de se forçar a aprender sua maneira de fazer as coisas.
Apenas meu $ 0,02