Como apresentar corretamente um popover de um uitableViewCell com UipopoverRowDirectionRight ou UIPOPARROWROWDirectionLeft
-
26-09-2019 - |
Pergunta
Eu sempre tento apresentar um povove de uma célula dentro de uma tabela de tabela desta maneira:
[myPopover presentPopoverFromRect:cell.frame inView:self.tableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Mas não posso usar o UipopoverRowDirectionRight ou para a esquerda, porque, dependendo da posição do iPad (retrato ou paisagem), o popover aparece em outro lugar.
Estou apresentando a popover da maneira certa?
PS: A visualização da tabela está na visualização detalhada de um SplitView.
Solução
Aqui está a solução simples que funciona bem para mim
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGRect rect=CGRectMake(cell.bounds.origin.x+600, cell.bounds.origin.y+10, 50, 30);
[popOverController presentPopoverFromRect:rect inView:cell permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Outras dicas
Você está obtendo o quadro da célula através do método RectForgundexpath. Isto está certo. No entanto, a TableView provavelmente é uma subjecionar de uma visualização maior do iPad, portanto, quando a popover obtém as coordenadas, acha que elas estão na visão maior. É por isso que o popover aparece no lugar errado.
Por exemplo, o CGrect para a linha é (0,40,320,44). Em vez do ponto de vista do popover esse quadro na visualização de tabela, ele tem como alvo esse quadro na sua visualização principal.
Resolvi esse problema convertendo o quadro das coordenadas relativas da tabela para coordenadas em minha visão maior.
código:
CGRect aFrame = [self.myDetailViewController.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:theRow inSection:1]];
[popoverController presentPopoverFromRect:[self.myDetailViewController.tableView convertRect:aFrame toView:self.view] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
Espero que ajude outras pessoas a procurar esse problema.
Encontrei esse problema hoje e encontrei uma solução mais simples.
Ao instantar a popover, você precisa especificar a visualização de conteúdo da célula:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *aViewController = [[UIViewController alloc] init];
// initialize view here
UIPopoverController *popoverController = [[UIPopoverController alloc]
initWithContentViewController:aViewController];
popoverController.popoverContentSize = CGSizeMake(320, 416);
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[popoverController presentPopoverFromRect:cell.bounds inView:cell.contentView
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[aView release];
// release popover in 'popoverControllerDidDismissPopover:' method
}
Em Swift, entre as respostas acima, isso funciona para mim em um iPad em qualquer orientação:
if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {
let cellRect = tableView.rectForRowAtIndexPath(indexPath)
popOverPresentationController.sourceView = tableView
popOverPresentationController.sourceRect = cellRect
popOverPresentationController.permittedArrowDirections = UIPopoverArrowDirection.Any
}
Para estourar uma popa ao lado do acessório, você pode usar este código :)
Eu uso isso para mais Uso avançado:
- Encontra AccesoryView personalizado (Cell.AccesoryView)
- Se vazio, encontre o accesoryview gerado (uibutton) se a célula tiver
- Se o UIBIBLETTON não existir, encontre o celular View (uitableViewCellContentView)
- Se a visualização do conteto de célula não existir, use a vista da célula
Pode ser usado para UIActionSheet ou UipopoverController.
Aqui está o meu código:
UIView *accessoryView = cell.accessoryView; // finds custom accesoryView (cell.accesoryView)
if (accessoryView == nil) {
UIView *cellContentView = nil;
for (UIView *accView in [cell subviews]) {
if ([accView isKindOfClass:[UIButton class]]) {
accessoryView = accView; // find generated accesoryView (UIButton)
break;
} else if ([accView isKindOfClass:NSClassFromString(@"UITableViewCellContentView")]) {
// find generated UITableViewCellContentView
cellContentView = accView;
}
}
// if the UIButton doesn't exists, find cell contet view (UITableViewCellContentView)
if (accessoryView == nil) {
accessoryView = cellContentView;
}
// if the cell contet view doesn't exists, use cell view
if (accessoryView == nil) {
accessoryView = cell;
}
}
[actionSheet showFromRect:accessoryView.bounds inView:accessoryView animated:YES];
Testado no iOS 4.3 a 5.1
Melhor usar como método personalizado:
-(UIView*)getViewForSheetAndPopUp:(UITableViewCell*)cell;
E código do método:
-(UIView*)getViewForSheetAndPopUp:(UITableViewCell*)cell {
UIView *accessoryView = cell.accessoryView;
if (accessoryView == nil) {
UIView *cellContentView = nil;
for (UIView *accView in [cell subviews]) {
if ([accView isKindOfClass:[UIButton class]]) {
accessoryView = accView;
break;
} else if ([accView isKindOfClass:NSClassFromString(@"UITableViewCellContentView")]) {
cellContentView = accView;
}
}
if (accessoryView == nil) {
accessoryView = cellContentView;
}
if (accessoryView == nil) {
accessoryView = cell;
}
}
return accessoryView;
}
Eu também encontrei esse problema. Uma solução para mim foi simplesmente mudar a largura do ret retornou por CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath
:
CGRect rect = [aTableView rectForRowAtIndexPath:indexPath];
//create a 10 pixel width rect at the center of the cell
rect.origin.x = (rect.size.width - 10.0) / 2.0;
rect.size.width = 10.0;
[self.addExpensePopoverController presentPopoverFromRect:rect inView:aTableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Isso cria um reto centrado dentro da célula. Dessa forma, o popover tem mais chances de encontrar um bom local para se posicionar.
O quadro celular vai ser algo como 0,0, largura, tamanho, não acredito que ele tenha seus x e y em relação à tabela de tabela ... você deseja usar - (cgrect) RectForgundexPath: (NSindexPath *) IndexPath para Isso, isso deve devolver o quadro correto para a célula em relação à TableView ... aqui está um link UabableView Ref
Eu tive o mesmo tipo de problema, aqui está a solução alternativa que usei:
- No meu uitableViewCell, adicionei ações (Ibactions, enquanto gero minhas células a partir de uma ponta) para os botões específicos da célula.
- Em seguida, defini um protocolo CellActionDelegate que imita meus seletores de ações, para os quais eu tinha meu botão (remetente) e minha célula (eu)
- Em seguida, o detalheViewController do meu SplitViewController implementa esse protocolo, convertendo da célula para suas coordenadas ...
Aqui um exemplo de código
Em myCustomTableViewCell.M:
-(IBAction)displaySomeCellRelativePopover:(id)sender{
//passes the actions to its delegate
UIButton *button = (UIButton *)sender;
[cellActionDelegate displaySomeCellRelativePopoverWithInformation:self.info
fromButton:button
fromCell:self];
}
e o MyDetailViewController.M:
-(void)displaySomeCellRelativePopoverWithInformation:(MyCellInformationClass *)info
fromButton:(UIButton *)button
fromCell:(UIView *)cell{
UIPopoverController * popoverController = nil;
//create your own UIPopoverController the way you want
//Convert your button/view frame
CGRect buttonFrameInDetailView = [self.view convertRect:button.frame fromView:cell];
//present the popoverController
[popoverController presentPopoverFromRect:buttonFrameInDetailView
inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];]
//release objects created...
}
PS: Claro, a 'ação' não precisa ser uma ibacção, e o quadro de onde a popover se origina não precisa ser um uibutton - um único uiview seria bom :)
Foi assim que eu fiz e funciona perfeitamente bem.
RidersVC *vc = [RidersVC ridersVC];
vc.modalPresentationStyle = UIModalPresentationPopover;
vc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
UIPopoverPresentationController *popPresenter = [vc popoverPresentationController];
popPresenter.sourceView = vc.view;
popPresenter.barButtonItem= [[UIBarButtonItem alloc] initWithCustomView:button];
popPresenter.backgroundColor = [UIColor colorWithRed:220.0f/255.0f green:227.0f/255.0f blue:237.0f/255.0f alpha:1.0];
[self.parentVC presentViewController:vc animated:YES completion:NULL];
Isso também funcionou para mim:
//Which are the ABSOLUTE coordinates in from the current selected cell CGRect frame =[self.view convertRect:[tbvEventsMatch rectForRowAtIndexPath:indexPath] fromView:tbvEventsMatch.viewForBaselineLayout];
A resposta aceita não pode compilar agora.
CGRect rect =[tableView rectForRowAtIndexPath:indexPath]; //This is how to get the correct position on the tableView
UIPopoverPresentationController *popController = [controller popoverPresentationController];
popController.sourceRect = rect;
popController.permittedArrowDirections = 0; //Here there is no arrow. It is my app's need
popController.delegate = self;
popController.sourceView = self.tableView;
popController.sourceView.backgroundColor = [UIColor yellowColor];