【问题标题】:UICollectionView Views Layer PriorityUICollectionView 视图层优先级
【发布时间】:2013-08-16 21:13:38
【问题描述】:

我发现 UICollectionViews 的行为非常奇怪。

这是场景。

我有一个 UIViewController 已被推送到 UINavigationController 堆栈。

UIViewController 视图在网格布局中有导航栏和 UICollectionView。 3 格宽 x 无限高。

就在屏幕范围的下方,我还隐藏了一个 UIToolbar。 UIToolbar 在层级中位于 UICollectionView 之上。

然后我允许用户将视图置于“编辑模式”,并将 UIToolbar 动画到屏幕上并覆盖 UICollectionView 的底部。如果用户离开“编辑模式”,我会将 UIToolbar 移出屏幕。

在“编辑模式”下,我允许用户多选带有复选框的单元格,并且 uitoolbar 具有删除按钮。

删除执行以下操作:

- (void)deletePhotos:(id)sender {
if ([[self.selectedCells allKeys] count] > 0) {
    [[DataManager instance] deletePhotosAtIndexes:[self.selectedCells allKeys]];
    [self.selectedCells removeAllObjects];
    [self.collectionview reloadData];
    [self.collectionview performBatchUpdates:nil completion:nil];
}
}

// Data Manager method in singleton class:

- (void)deletePhotosAtIndexes:(NSArray *)indexes {
NSMutableIndexSet *indexesToDelete = [NSMutableIndexSet indexSet];
for (int i = 0; i < [indexes count]; i++) {
    [indexesToDelete addIndex:[[indexes objectAtIndex:i] integerValue]];
    NSString *filePath = [self.photosPath stringByAppendingPathComponent:[self.currentPhotos objectAtIndex:[[indexes objectAtIndex:i] integerValue]]];
    NSString *thumbnailPath = [self.thumbPath stringByAppendingPathComponent:[self.currentPhotos objectAtIndex:[[indexes objectAtIndex:i] integerValue]]];
    if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]) {
        [[NSFileManager defaultManager] removeItemAtPath: filePath error:NULL];
        [[NSFileManager defaultManager] removeItemAtPath: thumbnailPath error:NULL];
    }
}
[self.currentPhotos removeObjectsAtIndexes:indexesToDelete];
}

数据管理器包含照片对象,并像这样用于单元格创建。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{    
ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"imageCell" forIndexPath:indexPath];

NSString  *pngfile = [[[DataManager instance] thumbPath] stringByAppendingPathComponent:[[[DataManager instance] currentPhotos] objectAtIndex:indexPath.row]];

if ([[NSFileManager defaultManager] fileExistsAtPath:pngfile]) {
    NSData *imageData = [NSData dataWithContentsOfFile:pngfile];
    UIImage *img = [UIImage imageWithData:imageData];
    [cell.imageView setImage:img];
}

if ([self.selectedCells objectForKey:[NSString stringWithFormat:@"%d", indexPath.row]] != nil) {
    cell.checkbox.hidden = NO;
} else {
    cell.checkbox.hidden = YES;
}

return cell;
}

所以这里是我发现问题的地方:

当删除足够多的单元格以使可见行数发生变化时,UIToolbar 正在消失。在整行 3 的情况下,如果我只删除 1 或 2 个项目,UIToolbar 不会消失。我没有在删除方法中的 UIToolbar 上做任何动画,只有在点击结束编辑模式的完成按钮时。我已确认没有调用此方法。

我还确认 UIToolbar 实际上并没有移动。如果我在 UIToolbar 通常会消失的情况下在点击删除时添加“self.collectionview removeFromSuperView”,那么 UIToolbar 正是屏幕上预期的位置。这给我的印象是 UICollectionView 在绘制父视图时以某种方式改变了图层层次结构。

我已尝试为 UIToolbar 带来 SubviewToFront,为 collectionview 尝试 sendSubviewToBack,但没有任何影响。

重新启动打开的工具栏会导致 uitoolbar 重新设置动画。但奇怪的是,它似乎从屏幕下方开始设置动画!这是没有意义的,除非 UICollectionView 在我调用 removeFromSuperview 调用之后以某种方式将 UIToolbar 推离屏幕,因此我无法重新创建。

我的一个“解决方案”是强制 UIToolbar 在 0.01 秒延迟后返回原位但没有动画

    [self performSelector:@selector(showToolbarNoAnimation) withObject:nil afterDelay:0.01];

这行得通。

这是一个问题: 知道为什么 UICollectionView 在删除整行后导致此行为将 UIToolbar 推到屏幕外吗? hack 有效,但没有解释问题。

谢谢, 詹姆斯

【问题讨论】:

  • 你在使用自动布局吗?
  • 是的。 UIToolbar 在屏幕外与 UICollectionView 的底部边缘对齐。

标签: uicollectionview autolayout


【解决方案1】:

当您使用自动布局并且您的视图是从情节提要(或 xib)加载时,您无法设置视图的框架。这样做一开始似乎可行,但在某些时候,自动布局会根据约束重置视图的框架,你不会明白发生了什么,然后你会发布一个问题到堆栈溢出。

如果您需要更改视图的布局,则需要更新视图的约束。

有一个约束指定工具栏底边与其父视图底边之间的距离。大概这个距离是 -44(其中 44 是工具栏的高度)。

您需要将该约束连接到视图控制器中的插座。出口的类型为NSLayoutConstraint *。叫它toolbarBottomEdgeConstraint

当您想在屏幕上设置工具栏的动画时,将约束的constant 设置为零并在动画块中调用layoutIfNeeded

- (void)showToolbarAnimated {
    [UIView animateWithDuration:0.25 animations:^{
        self.toolbarBottomEdgeConstraint.constant = 0;
        [self.toolbar layoutIfNeeded];
    }];
}

要隐藏工具栏,请将约束的 constant 设置回其原始值:

- (void)hideToolbarAnimated {
    [UIView animateWithDuration:0.25 animations:^{
        self.toolbarBottomEdgeConstraint.constant = -toolbar.bounds.size.height;
        [self.toolbar layoutIfNeeded];
    }];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 2011-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多