UICollectionView水平滚动,删除最后一项,动画不工作 [英] UICollectionView horizontal scrolling, deleting last item, animation not working

查看:308
本文介绍了UICollectionView水平滚动,删除最后一项,动画不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个UICollectionView。它水平滚动,只有一行项目,并且行为像一个分页UIScrollView。我正在沿着Safari标签选择器的线做一些东西,所以你仍然可以看到每个项目的边缘。

I have a UICollectionView. It scrolls horizontally, has only a single row of items, and behaves like a paging UIScrollView. I'm making something along the lines of the Safari tab picker, so you can still see the edge of each item. I only have one section.

如果我删除了不是最后一个项目的项目,一切都会按预期运行,一个新项目会从右侧滑入。

If I delete an item that is not the last item, everything works as expected and a new item slides in from the right.

如果我删除最后一个项目,那么集合视图的滚动位置跳转到第N-1个项目(不能平滑地动画化),然后我看到第N个项目我删除了)淡出。

If I delete the last item, then the collection view's scroll position jumps to the N-1th item (doesn't smoothly animate), and then I see the Nth item (the one I deleted) fade out.

这种行为与我做的自定义布局无关,因为即使我切换它使用纯流布局,它也会发生。我正在删除项目:

This behaviour isn't related to the custom layout I made, as it occurs even if I switch it to use a plain flow layout. I'm deleting the items using:

[self.tabCollectionView deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:index inSection:0]]];

有没有人体验过这个?是UICollectionView中的一个错误,是否有解决方法?

Has anyone else experienced this? Is it a bug in UICollectionView, and is there a workaround?

推荐答案

我设法使用标准< c $ c> UICollectionViewFlowLayout 。我不得不手动创建动画。

I managed to get my implementation working using the standard UICollectionViewFlowLayout. I had to create the animations manually.

首先,我使用基本动画使已删除的单元格淡出:

First, I caused the deleted cell to fade out using a basic animation:

- (void)tappedCloseButtonOnCell:(ScreenCell *)cell {

    // We don't want to close our last screen.
    if ([self screenCount] == 1u) {
        return;
    }

    [UIView animateWithDuration:UINavigationControllerHideShowBarDuration
                     animations:^{
                         // Fade out the cell.
                         cell.alpha = 0.0f;
                     }
                     completion:^(BOOL finished) {

                         NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
                         UIViewController *screen = [self viewControllerAtIndex:indexPath.item];

                         [self removeScreen:screen animated:YES];
                     }];
}



接下来,我使集合视图滚动到上一个单元格。一旦我滚动到所需的单元格,我删除已删除的单元格。

Next, I caused the collection view to scroll to the previous cell. Once I've scrolled to the desired cell, I remove the deleted cell.

- (void)removeScreen:(UIViewController *)screen animated:(BOOL)animated {

    NSParameterAssert(screen);

    NSInteger index = [[self.viewControllerDictionaries valueForKeyPath:kViewControllerKey] indexOfObject:screen];

    if (index == NSNotFound) {
        return;
    }

    [screen willMoveToParentViewController:nil];

    if (animated) {

        dispatch_time_t popTime = DISPATCH_TIME_NOW;
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index
                                                 inSection:0];

        // Disables user interaction to make sure the user can't interact with
        // the collection view during the time between when the scroll animation
        // ends and the deleted cell is removed.
        [self.collectionView setUserInteractionEnabled:NO];

        // Scrolls to the previous item, if one exists. If we are at the first
        // item, we just let the next screen slide in from the right.
        if (index > 0) {
            popTime = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC);
            NSIndexPath *targetIndexPath = [NSIndexPath indexPathForItem:index - 1
                                                  inSection:0];
            [self.collectionView scrollToItemAtIndexPath:targetIndexPath
                                        atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
                                                animated:YES];
        }

        // Uses dispatch_after since -scrollToItemAtIndexPath:atScrollPosition:animated:
        // doesn't have a completion block.
        dispatch_after(popTime, dispatch_get_main_queue(), ^{

            [self.collectionView performBatchUpdates:^{
                [self.viewControllerDictionaries removeObjectAtIndex:index];
                [self.collectionView deleteItemsAtIndexPaths:@[indexPath]];
                [screen removeFromParentViewController];
                [self.collectionView setUserInteractionEnabled:YES];
            } completion:NULL];
        });

    } else {
        [self.viewControllerDictionaries removeObjectAtIndex:index];
        [self.collectionView reloadData];
        [screen removeFromParentViewController];
    }

    self.addPageButton.enabled = YES;
    [self postScreenChangeNotification];
}

唯一有问题的部分是 dispatch_after ()。不幸的是, -scrollToItemAtIndexPath:atScrollPosition:animated:没有完成块,所以我不得不模拟它。为了避免计时问题,我禁用了用户交互。这可以防止用户在删除单元之前与集合视图交互。

The only part that is slightly questionable is the dispatch_after(). Unfortunately, -scrollToItemAtIndexPath:atScrollPosition:animated: does not have a completion block, so I had to simulate it. To avoid timing problems, I disabled user interaction. This prevents the user from interacting with the collection view before the cell is removed.

我不得不注意的另一件事是我必须将单元格的alpha重置为1,由于单元格的重用。

Another thing I had to watch for is I have to reset my cell's alpha back to 1 due to cell reuse.

我希望这可以帮助您使用Safari样式标签选择器。我知道你的实现与我不同,我希望我的解决方案也为你工作。

I hope this helps you with your Safari-style tab picker. I know your implementation is different from mine, and I hope that my solution works for you too.

这篇关于UICollectionView水平滚动,删除最后一项,动画不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆