iOS7的子视图如果超出父视图边界则被裁剪

7

我查看了苹果发布的新 UI 信息 - 没有帮助。

现在让代码和截图来展示我遇到的问题。为了确保不是我的有 bug 的代码,我创建了一个新项目,只包含一个文件 - 一个内部有 tableView 的 UIViewController,委托已经设置好。

我做了以下操作:

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    // Return the number of sections.
    return 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    return 3;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"UITableViewCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"%d",indexPath.row];
    // Configure the cell...

    UIView * redView = [[UIView alloc] initWithFrame:CGRectMake(0, -10, 100, 20)];
    redView.backgroundColor = [UIColor redColor];
    [cell addSubview:redView];

    return cell;
}

表格视图设置为分组。 让我们在iOS 6上运行它: 当然,Y坐标原点是负数! 是的,确实如此,这就是我想要实现的结果。 让我们看看在iOS 7上会显示什么: 提示:如果我们将redView添加到普通的UIView中,则不会发生这种情况。
另一个提示:如果我将tableView的背景颜色设置为蓝色,则分区之间的灰色线条将变为蓝色,而不是灰色(以演示灰色不是设置的标题)。 另一个提示:iPad也是如此。
为什么在iOS 7中会裁剪超出边界的所有内容?请帮忙!

你尝试过将单元格的clipsToBounds属性设置为NO吗? - Michał Zygar
是的,它没有起作用,但感谢您的提示。 - Dumoko
3个回答

8
因为iOS 7对UITableViewCells的视图层次结构进行了一些更改。
以前是UITableViewCell 视图 -> 内容视图
现在更像UITableViewCell 视图 -> 滚动视图 -> 内容视图
解决方法是在scrollView上设置clipsToBounds = NO(默认设置为YES)。而实现这一点的方法是通过superview属性。
所以基本上在iOS6及其之前,为允许内容溢出单元格边界,您需要执行以下操作:
self.clipsToBounds = NO;                        //cell's view
self.contentView.clipsToBounds = NO;            //contentView

在iOS7中,您还需要防止滚动视图被裁剪,因此您可以执行以下操作:

In iOS7中,您还需要防止滚动视图被裁剪,因此您可以执行以下操作:

self.clipsToBounds = NO;                        //cell's view
self.contentView.clipsToBounds = NO;            //contentView
self.contentView.superview.clipsToBounds = NO;  //scrollView

我使用的向后兼容解决方案是:

self.clipsToBounds = NO;
self.contentView.clipsToBounds = NO;
if ([self.contentView.superview isKindOfClass:[NSClassFromString(@"UITableViewCellScrollView") class]]) self.contentView.superview.clipsToBounds = NO;

请记住这是一个Hacky™的解决方案,如果在iOS 8中视图层次结构发生变化,可能会出现问题。不幸的是,似乎苹果不希望我们让UITableViewCells溢出内容,所以据我所知,这是唯一可行的解决方案。


2
以下是解决方法: cell.layer.masksToBounds = NO 然而,这可能会破坏其他东西,例如单元格动画。
您遇到的问题是由于单元格不支持在其范围之外绘制内容所导致的(实际上,使用超出父视图范围的子视图始终是一种hacky解决方案)。
最好的建议是重新设计并尽量避免这样的功能。
另一种解决方法可能是将相同的视图添加到前一个单元格的底部或直接将它们作为UITableView的子视图添加。

maskToBounds完全没有起作用,我尝试在自定义单元格类的init方法和cellforrow tableView数据源方法中都使用它... 我正在尝试遵循您的最佳建议,并通过headerforsection数据源方法正确地完成它。但仍在等待,也许有人会提出解决所描述情况的解决方案... - Dumoko

2

我认为内容实际上并没有像 masksToBounds 一样被裁剪,而是视图被其他(不透明的)单元格遮盖。您可以尝试通过更改UITableView子视图的顺序(“z-Index”),每当单元格出现时使用bringSubviewToFront:和类似方法来确保最靠近屏幕底部的单元格是所有单元格中最前面的视图。


我尝试了许多修复方法,考虑到这可能是问题,但都没有起作用。不过还是谢谢您的时间! - Dumoko
@Theo,你找到了问题所在,但不幸的是bringSubviewToFront并不能解决它。它只会将子视图置于单元格内容视图中的前面,而不是整个表视图中。这意味着,遮盖单元格的UITableViewCell仍然在前面。 - Anish Kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接