BLOG
FILTROS
TAGS MAIS USADAS
UIPickerView circular - "Gambiarra oficial" da Apple
-
AUTOR
Felipe Barreto
TAGs desenvolvimento, iphone sdk
2 COMENTÁRIOS-
Tweet
Para quem não conhece, o UIPickerView é o componente do iPhone que parece um letreiro de máquinas caça-níquel e é normalmente utilizado em situações onde você tem que escolher uma dentre várias opções.

Não vou me aprofundar sobre o uso deste componente em situações normais, pois já existe documentação suficiente para isso, mas pretendo explorar uma maneira de estender seu comportamento, permitindo que a lista de opções apareça de uma maneira circular, num loop infinito.
O componente padrão, infelizmente, não possui qualquer mecanismo para viabilizar essa funcionalidade, contudo existe um outro componente, UIDatePicker, que utiliza o UIPickerView com uma lista circular para escolher dias, minutos, etc. Vendo isso, conclui: "bom, tem um jeito.. a Apple só não quer nos contar qual".

Procurando o truque
Coloquei o UIDatePicker numa app de teste para rodar no iPhone e ativei o modo de debug para começar a destrinchar o componente. Fiz um passeio entre dezenas de views e subviews, trocando ponteiros em tempo de execução, chamando métodos de objetos que nunca teria acesso de modo normal, entre outras coisas que crianças não devem tentar em casa :) e acabei topando com a solução para o problema. E me surpreendi!
Expondo a gambiarra
O UIPickerView sempre deve ser associado a um UIPickerViewDataSouce e a um UIPickerViewDelegate que vão prover as informações necessárias para montar o componente.
Vou assumir que existe um array que será a base de dados para o componente.
NSArray *meusItens;
O UIPickerViewDataSouce possui um método que define o número de linhas (rows) que cada subcomponente do UIPickerView deverá exibir. É aí que começa o truque.
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [meusItens count] * 10000;
}
Observe que multipliquei o numero de elementos do array por 10.000!! Sim! Este é o macete que a Apple usa para fazer uma lista "infinita". Não tem nada de infinita, mas sim uma lista suficientemente grande para que somente os usuário mais chatos curiosos consigam chegar ao fim.
Para completar o truque, a lista de 10000 x N opções deve ser exibida a partir da metade. Desta maneira, ela terá scroll "infinito" em qualquer direção. Basta colocar a linha a seguir no viewDidLoad do seu controlador, ou onde achar melhor.
[minhaPickerView selectRow:([meusItens count]*5000) inComponent:0 animated:NO];
Repare que posicionei a minhaPickerView na posição 5000 x N, ou seja, na metade da lista.
Quando for necessário mapear uma linha qualquer dentro do seu array - como na hora de definir o conteúdo de cada linha ou decidir o que fazer quando o usuário escolher uma linha - basta usar o seguinte código.
[meusItens objectAtIndex:(row % [meusItens count])];
O que eu fiz foi aplicar o operador módulo (%) sobre o número da linha usando o tamanho da lista original. O resultado será sempre um inteiro entre 0 e o tamanho da lista menos 1 - que é o necessário para acessar todos os itens do array.
Pronto! Agora você tem uma lista circular com o carimbo da Apple :)

OBS: Utilize este recurso apenas se sua lista possuir um número razoável de elementos, pois se ela tiver até 4 ou 5, um ou mais elementos aparecerão duplicados na tela - o que ficaria bem esquisito.
Bom, é isto! Espero que tenha ficado claro, mas se restar dúvida, fique a vontade para colocá-la nos comentários.
POSTS RELACIONADOS:
2 COMENTÁRIOs
-
Daniel Bonates 25/12/2009, 18:13
Olá, parabéns pela descoberta! E obrigado pelo "crianças não devem tentar em casa!" Deu até medo! rsrs
Só o que não consegui fazer foi começar selecionando o elemento láaa da metade, pois a linha:
[minhaPickerView selectRow:([meusItens count]*5000) inComponent:0 animated:NO];
não surtiu efeito algum no viewDidLoad. Será que é porque eu defini o array de objetos justamente na linha anterior a essa?? Esta assim no viewDidLoad: humores = [[NSArray alloc] initWithObjects: @"Estático", @"Feliz", @"Alegre", @"Muito bem", @"Cansado", @"Sem graça", @"Deprimido", @"Oprimido", nil];
[humorPicker selectRow:([humores count]*5000) inComponent:0 animated:NO];humorPicker é o picker e humores o array...
alguma direção?
De qq forma, valeu! Abraço :)
-
Felipe Barreto 28/12/2009, 11:31
Fala Daniel,
pode ser realmente porque ainda não foi carregada a lista. Experimente mover o código que seleciona a metade da lista para o viewWillAppear.
Abraço!





+55 21 3553-1898