O UICollectionView “deslizar” no gerenciador de aplicativos iOS7?
-
21-12-2019 - |
Pergunta
Em qualquer iPhone ou iPad 2014+, clique duas vezes no botão home para ver o "gerenciador de aplicativos"
Este é um UICollectionView esquerdo-direito, MAS tem um gesto de "deslizar".deslize para cima.Como isso é feito?Não é tão fácil “remover” uma célula de um UICollectionView.
Nota de rodapé para googlers.para o problema geral de "descascar", "arrancar", uma célula de uma visualização de coleção, aqui está uma explicação completa e organizada: https://stackoverflow.com/a/24339705/294884 Espero que ajude alguém.
Solução
Pode ser muito mais simples do que os comentários da sua pergunta sugerem.
Sua célula deve conter uma visualização (aquilo que você vai arrastar) e você adiciona um UIPanGestureRecognizer a essa visualização.
No método de ação do gesto, você move a visualização para cima ou para baixo e, quando ela fica distante o suficiente para que você queira excluí-la, basta animá-la.Há muitas perguntas aqui relacionadas a esta parte.
Isso deixa uma lacuna em sua coleção e agora você precisa movimentar as coisas.Acontece que isso é bastante simples:
[_collectionView performBatchUpdates:^{
[_collectionView deleteItemsAtIndexPaths:@[indexPath]];
} completion:^(BOOL finished) {
// you might want to remove the data from the data source here so the view doesn't come back to life when the collection view is reloaded.
}];
O material à direita da célula removida desliza e estamos todos bem.
Outro problema a ser superado:certificando-se de que seu reconhecedor de gestos e a visualização da coleção funcionem bem juntos.Felizmente, isso também não é muito complicado.
[_collectionView.panGestureRecognizer requireGestureRecognizerToFail:pgr]; //where pgr is the recognizer you made for dragging the view off
Isso significa que para que o gesto panorâmico da visualização da coleção funcione, o seu deve falhar.Então você vai querer configurar o seu para que ele só funcione ao mover para cima e para baixo, e deixar a visualização da coleção ainda funcionar para movimentos panorâmicos da esquerda para a direita.No delegado do seu reconhecedor de gestos, implemente o método a seguir, que simplesmente verifica se você está se movendo mais no eixo x ou no eixo y.
-(BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
CGPoint translation =[gestureRecognizer translationInView:self.view];
return(translation.x * translation.x > translation.y * translation.y);
}
Outras dicas
Eu estava procurando por essa funcionalidade e usando a sugestão do @mbehan, falsifiquei essa funcionalidade usando UICollectionView.
O que fiz foi adicionar uma visualização de tamanho menor em uma célula de coleção (fundo transparente) e adicionar um único gesto panorâmico em CollectionView (não em cada célula). Em seguida, no gesto panorâmico, movo a visualização e parece que a célula está se movendo.Depois que a visualização atinge algum ponto, primeiro a escondo e, em seguida, excluo a célula da visualização da coleção.
Hierarquia celular:CollectionViewCell -> View (Tag Value == 2) -> Uilabel (Tag Value == 1) O rótulo é usado apenas para fins de espaço reservado.
estou postando meu código abaixo:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = (UICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"Cards" forIndexPath:indexPath];
UILabel *lblNumber = (UILabel*)[cell.contentView viewWithTag:1];
UIView *viewTouch = (UIView*)[cell.contentView viewWithTag:2];
[viewTouch setHidden:NO];
[lblNumber setText:arrCards[indexPath.row]];
return cell;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 50, 0, 30);
}
-(BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
if([gestureRecognizer isEqual:panGesture]) {
CGPoint point = [(UIPanGestureRecognizer*)gestureRecognizer translationInView:collectionView_];
if(point.x != 0) { //adjust this condition if you want some leniency on the X axis
//The translation was on the X axis, i.e. right/left,
//so this gesture recognizer shouldn't do anything about it
return NO;
}
}
return YES;
}
- (IBAction)panGestureCalled:(UIPanGestureRecognizer *)sender {
yFromCenter = [sender translationInView:collectionView_].y; //%%% positive for up, negative for down
UIView *view = sender.view;
CGPoint location = [view.superview convertPoint:view.center toView:collectionView_];
NSIndexPath *indexPath = [collectionView_ indexPathForItemAtPoint:location];
UICollectionViewCell *cell = [collectionView_ cellForItemAtIndexPath:indexPath];
UIView *touchView = (UIView*)[cell.contentView viewWithTag:2];
switch (sender.state) {
case UIGestureRecognizerStateBegan:{
originalPoint = touchView.center;
break;
};
case UIGestureRecognizerStateChanged:{
touchView.center = CGPointMake(originalPoint.x , originalPoint.y + yFromCenter);
break;
};
//%%% let go of the card
case UIGestureRecognizerStateEnded: {
CGFloat velocityY = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:collectionView_].y);
if (velocityY < -30 && yFromCenter<0) {
[self hideView:touchView withDuration:0.2 andIndexPath:indexPath];
}else if ((yFromCenter< 0 && yFromCenter > -200) || yFromCenter > 0){
CGFloat animationDuration = (ABS(velocityY)*.0002)+.2;
[self resettleViewToOriginalPosition:touchView andDuration:animationDuration];
}else
[self hideView:touchView withDuration:0.2 andIndexPath:indexPath];
};
break;
case UIGestureRecognizerStatePossible:break;
case UIGestureRecognizerStateCancelled:break;
case UIGestureRecognizerStateFailed:break;
}
}
-(void)resettleViewToOriginalPosition:(UIView*)view andDuration:(float)duration{
[UIView animateWithDuration:duration
delay:0.0f
options: UIViewAnimationOptionCurveEaseOut
animations:^
{
[view setCenter:originalPoint];
}
completion:^(BOOL finished)
{
}];
}
- (void)hideView:(UIView*)view withDuration:(float)duration andIndexPath:(NSIndexPath*)indexPath
{
[UIView animateWithDuration:duration
delay:0.0f
options: UIViewAnimationOptionCurveEaseOut
animations:^
{
CGRect frame = view.frame;
frame.origin.y = -300;
view.frame = frame;
}
completion:^(BOOL finished)
{
[view setHidden:YES];
CGRect frame = view.frame;
frame.origin.y = 39;
view.frame = frame;
NSLog(@"View is hidden.");
[arrCards removeObjectAtIndex:indexPath.row];
[collectionView_ performBatchUpdates:^{
[collectionView_ deleteItemsAtIndexPaths:@[indexPath]];
} completion:^(BOOL finished) {
// you might want to remove the data from the data source here so the view doesn't come back to life when the collection view is reloaded.
}];
}];
}
e mantenha pagingEnabled de CollectionView como NO e então estará pronto.