我怎么能添加一个阴影分组的UITableView(正如在官方的Twitter应用程序中看到的)?

我有一个标准的分组表格视图。 我想为它添加一个阴影(即在每个tableview部分的边缘) – 如果您不确定我的意思,请参阅官方的twitter应用程序(下面)作为示例。 这是非常微妙的,但它绝对是一个阴影,而不是一个边界。

Twitter应用程序

我怎样才能达到这个效果?

保存为阴影内置图像作为每个单元格的背景 – 这将不允许animation单元格resize,如我所需 – 我还没有想出一个办法。

我有一天在自己的应用程序中需要这个效果。 实际上,通过将CALayer阴影属性与CALayer掩码结合使用,实现起来非常简单。 我在Github上做了一个简单的示例项目:

https://github.com/schluete/GroupedTableViewWithShadows

该效果在UITableViewCell类别UITableViewCell + CellShadows.m中实现 。

第一步是创build一个阴影矩形。 根据单元格在区域(顶部,中间,底部)中的位置放大矩形,以防止在错误的拐angular处显示圆angular(第18-23行)。 然后将阴影添加到单元格的背景视图(35-41行)。

现在有一个很好的阴影效果,但第一个单元格的阴影“stream血”到第二个单元格。 为了防止出血,只需添加一个图层蒙版,以切除所有不必要的阴影部分(25-32行和43-46行)。 就是这样,我们有我们的影子!

我有两个解决scheme可能有帮助。 由于圆angular,我认为你将不得不应用阴影效果的单元格,并定位它们,使阴影不重叠y轴。 所以…

解决scheme1 (复杂的解决scheme):这是我认为可以工作的解决scheme,如果你正在为cornerRadius设置animation,或者不确定单元格的确切形状。 你有没有尝试使用像Ecarrionbuild议的shadowPath,但将其应用到您的自定义UITableView单元格? 想象一下中央细胞的path(不是顶部和底部),它比x轴上的单元略宽,y轴上的单元更短。

那么你必须确保阴影投射在该部分的顶部和底部,而不使每个单独的阴影重叠,对吗? 所以对于顶部和底部的单元格,你可以在y轴上使阴影path更大,比方说4点大。 然后你调整这些单元格的shadowOffset属性,在y轴上也是4点。 如果中央单元格的shadowOffset是(0,0),那么顶部单元格是(0,-4),底部单元格是(0,4)。

如果是我,我会把各种尺寸和偏移量调整到一个plist,所以我可以修改小的细节,而不需要编辑代码。 只需将plist加载到字典或自定义类中,然后使用这些值设置属性。 使小调整less了很多烦恼。

编辑:超越使用shadowPath,你可以使一个复合的单元格的透明背景图层的tableview一个稍小的阴影层,然而一个更小的图层添加文本和图像。 阴影层基于文本/图像层,可能稍宽,高,较短等。将模糊应用于该图层,然后用矩形遮罩将其遮罩,以使阴影图层在下一个图层开始时结束。 使用顶层和底层时,遮罩必须向上或向下延伸到阴影效果出现的y轴上的最高/最低点(您仍然必须遮罩邻接下一个单元格的一侧)。 这取决于你愿意去达到一个确切的效果多远..​​….也许这给你更多的弹药。

解决scheme2 (稍微简单的解决scheme):如果您确切知道cornerRadius将在顶部和底部单元格上,而且您不一定知道的单元格的长度和/或宽度,则可以使用旧的“拉伸一像素graphics”的伎俩。

首先你Photoshop / Gimp的angular落阴影的图像。 如果宽度始终相同,则该图像可以是单元格整个顶部的阴影。 通过旋转相同的图像可以用于其他angular落或单元格的底部。

现在的窍门。 采用1×5的模糊或渐变效果的部分,你用于angular落阴影。 如果你的阴影效果是3个像素,那么做1×3等。导出为PNG或首选的格式,并检查如果你放置其边缘对angular的图像边缘无缝排列(模糊或渐变具有相同的颜色值没有一个可见的接缝)。

所有的单元格都会在单元格的可见部分旁边(左侧和右侧)用1×5图像作为图层内容。 也可以是一个拉伸的UIImageView,你的select。 这些排列使左右阴影。

将angular落阴影放置在部分中的第一个和最后一个单元格 – 它们可以是不同的自定义单元格,也可以devise单元格以便在创build时将其索引传递给它,并自行安排。 alignment你的侧面阴影,以便它们开始angular落阴影结束的位置,并向下延伸到单元格的底部。 如果你也在改变单元格的宽度,你将在两个angular落图像之间做同样的事情,在x轴上伸展你的渐变。

好吧,一张图片上写着千言万语,所以我似乎在推动这么多的话,这里是一个图像来说明:

为可缩放的边框或阴影效果伸展1px图像

其实你可以尝试使用正常模式tableView(不分组),并创build2个(或更多)types的单元格与每个具有特定的标识符。 一个用于顶部/左/右阴影,一个用于最后一个用于左/右/底部阴影,另一个用于其他单元用左/右阴影。 在你的tableView:cellForRowAtIndexPath:只是检查你是哪一行(例如indexPath.row == 0)并返回适当的单元格。

你总是可以像这样设置一个ShadowPath:

 myView.layer.shadowOpacity = 0.8; myView.layer.shadowRadius = 5.0; myView.layer.shadowOffset = CGSizeZero; myView.layer.shadowPath = [UIBezierPath bezierPathWithRect:myView.layer.bounds].CGPath; 

请注意,这需要QuartzCore或CoreGraphics,记不起来。

在这篇文章中有很多阴影path: http : //nachbaur.com/blog/fun-shadow-effects-using-custom-calayer-shadowpaths

提出一个老问题的风险,我觉得所提供的答案都没有提出任何体面的编码做法,也不是“干净和容易”。

我发现了一个更清洁的方法。 看看你的想法。 首先,你需要UITableViewCell 。 然后,无论是在标题或其他地方,作出三个单独的定义(例如):

 #define TOP_CELL 0 #define MIDDLE_CELL 1 #define BOTTOM_CELL 2 

现在,重写layoutSubviews:方法,并执行如下操作:

 -(void) layoutSubviews { [super layoutSubviews]; if([self tag] == BOTTOM_CELL) { self.layer.masksToBounds = NO; self.layer.shadowOffset = CGSizeMake(-10, 15); self.layer.shadowRadius = 5; self.layer.shadowOpacity = 0.5; } //else if middle_cell (Different shadowing) //else if top_cell (Different shadowing) } 

注意:我不确定layoutSubviews方法是否足够,我只知道它在dequeueReusableCellWithIdentifier:之后被调用dequeueReusableCellWithIdentifier:这对下一步很重要。

现在,在你的UITableViewDataSource ,在你的tableView:cellForRowAtIndexPath:

 CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:ident]; if(indexPath.row == 0) [cell setTag:TOP_CELL]; else if(indexPath.row == (NUMBER_OF_ROWS - 1)) [cell setTag:BOTTOM_CELL]; else [cell setTag: MIDDLE_CELL]; 

瞧! 阴影部分