2013-08-16 45 views
0

我看到一个非常奇怪的行为与UICollectionViews。UICollectionView视图图层优先级

这是场景。

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

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

只是在屏幕范围之下,我还隐藏了一个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正在消失。如果我只删除1或2个项目,UIToolbar不会消失。我没有在删除方法中的UIToolbar上做任何动画,只有当点击一个完成按钮,结束编辑模式。我已确认此方法未被调用。

我也确认UIToolbar并未实际移动。如果在UIToolbar正常消失的情况下在添加“self.collectionview removeFromSuperView”时添加了“self.collectionview removeFromSuperView”,则UIToolbar正好在屏幕上的预期位置。这给我的印象是UICollectionView以某种方式改变了父视图绘制中的图层层次结构。

我试图尝试为UIToolbar和sendSubviewToBack为collectionview带来SubviewToFront并没有任何影响。

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

一个“解决方案”我已经很给力了UIToolbar回来到位置,但没有动画0.01秒的延迟

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

这工作后。

这里是一个问题: 任何想法为什么UICollectionView导致这种行为推UIToolbar屏幕后删除整行?黑客的作品,但没有解释这个问题。

谢谢, 詹姆斯

+0

您是否使用自动布局? –

+0

是的。 UIToolbar在屏幕之外对齐到UICollectionView的底部边缘。 –

回答

1

当您使用自动布局,你的观点是从故事板加载(或厦门国际银行),则不能设置你的意见的框架。这样做看起来可能最初起作用,但是在某些时候,自动布局会根据约束来重置视图的框架,并且您不会理解发生了什么,然后您会向堆栈溢出发布问题。

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

存在一个约束,指定工具栏底部边缘与其超级视图底部边缘之间的距离。推测该距离是-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]; 
    }]; 
}