UITableViewCell:圆角和阴影

Sha*_*ngh 47 uitableview swift

我正在改变UITableViewCell的宽度,以便单元格更小,但用户仍然可以沿着tableview的边缘滚动.

override func layoutSubviews() {        
    // Set the width of the cell
    self.bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width - 40, self.bounds.size.height)
    super.layoutSubviews()
}
Run Code Online (Sandbox Code Playgroud)

然后我绕过角落:

cell.layer.cornerRadius = 8
cell.layer.masksToBounds = true
Run Code Online (Sandbox Code Playgroud)

到目前为止都很好.阴影会出现问题.边界被掩盖,因此阴影显然不会出现.我已经查找了其他答案,但似乎无法弄清楚如何沿着边界圆角显示阴影.

cell.layer.shadowOffset = CGSizeMake(0, 0)
cell.layer.shadowColor = UIColor.blackColor().CGColor
cell.layer.shadowOpacity = 0.23
cell.layer.shadowRadius = 4
Run Code Online (Sandbox Code Playgroud)

所以我的问题 - 如何减小宽度,绕角,并同时为UITableViewCell添加阴影?

更新:尝试R Moyer的回答

尝试R Moyer的回答

R M*_*yer 87

这个问题来得很愉快!我自己也完全解决了同样的问题.

  1. 在单元格的内容视图中创建一个UIView(让我们称之为mainBackground).这将包含您所有单元格的内容.定位它并在故事板中应用必要的约束.
  2. 创建另一个UIView.这个将是带阴影的那个(让我们称之为shadowLayer).完全按照您的方式定位它mainBackground,但在它后面,并应用相同的约束.
  3. 现在您应该可以设置圆角和阴影,如下所示:

    cell.mainBackground.layer.cornerRadius = 8  
    cell.mainBackground.layer.masksToBounds = true
    
    cell.shadowLayer.layer.masksToBounds = false
    cell.shadowLayer.layer.shadowOffset = CGSizeMake(0, 0)
    cell.shadowLayer.layer.shadowColor = UIColor.blackColor().CGColor
    cell.shadowLayer.layer.shadowOpacity = 0.23
    cell.shadowLayer.layer.shadowRadius = 4
    
    Run Code Online (Sandbox Code Playgroud)

但是,这里的问题是:计算每个单元格的阴影是一项缓慢的任务.当您滚动表格时,您会注意到一些严重的延迟.解决这个问题的最好方法是UIBezierPath为阴影定义一个,然后栅格化它.所以你可能想这样做:

cell.shadowLayer.layer.shadowPath = UIBezierPath(roundedRect: cell.shadowLayer.bounds, byRoundingCorners: .AllCorners, cornerRadii: CGSize(width: 8, height: 8)).CGPath
cell.shadowLayer.layer.shouldRasterize = true
cell.shadowLayer.layer.rasterizationScale = UIScreen.mainScreen().scale
Run Code Online (Sandbox Code Playgroud)

但这会产生一个新问题!形状UIBezierPath取决于shadowLayer边界,但是边界没有cellForRowAtIndexPath被调用时间正确设置.所以,你需要shadowPath根据shadowLayer边界进行调整.执行此操作的最佳方法是子类化UIView,并将属性观察器添加到bounds属性.然后设置阴影的所有属性didSet.请记住更改shadowLayer故事板中的类以匹配新的子类.

class ShadowView: UIView {
    override var bounds: CGRect {
        didSet {
            setupShadow()
        }
    }

    private func setupShadow() {
        self.layer.cornerRadius = 8
        self.layer.shadowOffset = CGSize(width: 0, height: 3)
        self.layer.shadowRadius = 3
        self.layer.shadowOpacity = 0.3
        self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 8, height: 8)).cgPath
        self.layer.shouldRasterize = true
        self.layer.rasterizationScale = UIScreen.main.scale
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 哇!是不是有一种更简单的方法来绕过角落并为集合视图单元创建阴影? (3认同)
  • 有史以来最简单,最天才的解决方案之一! (2认同)

Bor*_*zin 31

接受的答案有效,但添加额外的子视图以获得此效果几乎没有任何意义.这是有效的解决方案.

第1步:添加阴影和角半径

// do this in one of the init methods
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    // add shadow on cell
    backgroundColor = .clear // very important
    layer.masksToBounds = false
    layer.shadowOpacity = 0.23
    layer.shadowRadius = 4
    layer.shadowOffset = CGSize(width: 0, height: 0)
    layer.shadowColor = UIColor.blackColor().CGColor

    // add corner radius on `contentView`
    contentView.backgroundColor = .white
    contentView.layer.cornerRadius = 8
}
Run Code Online (Sandbox Code Playgroud)

第二步:掩盖到界限willDisplay

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // this will turn on `masksToBounds` just before showing the cell
    cell.contentView.layer.masksToBounds = true
}
Run Code Online (Sandbox Code Playgroud)

额外奖励:平滑滚动

// if you do not set `shadowPath` you'll notice laggy scrolling
// add this in `willDisplay` method
let radius = cell.contentView.layer.cornerRadius
cell.layer.shadowPath = UIBezierPath(roundedRect: cell.bounds, cornerRadius: radius).cgPath
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案。比为阴影添加单独的UIView干净得多。谢谢! (3认同)
  • 设置 tableviews clipsToBounds = false 后,此解决方案对我有用 (2认同)

Sai*_*ddy 20

cell.layer.cornerRadius = 10
cell.layer.masksToBounds = true
Run Code Online (Sandbox Code Playgroud)

  • 在 cellForItemAt indexPath 中 (2认同)

小智 14

要为单元格创建阴影和角落,您只需要一个backView.请参阅下面的示例.

在此输入图像描述

你必须添加backView和设置leading,trailing,top,bottom约束等于Content view.把你的内容backView与适当的约束,但要确保您的内容不超过海湾 [R backView.

之后在您的单元格初始化代码中添加以下行:

override func awakeFromNib() {
    super.awakeFromNib()

    backgroundColor = Colors.colorClear

    self.backView.layer.borderWidth = 1
    self.backView.layer.cornerRadius = 3
    self.backView.layer.borderColor = Colors.colorClear.cgColor
    self.backView.layer.masksToBounds = true

    self.layer.shadowOpacity = 0.18
    self.layer.shadowOffset = CGSize(width: 0, height: 2)
    self.layer.shadowRadius = 2
    self.layer.shadowColor = Colors.colorBlack.cgColor
    self.layer.masksToBounds = false
}
Run Code Online (Sandbox Code Playgroud)

不要忘记创建IBOutlet Back View.

结果如下:

在此输入图像描述

  • 它不适合我.阴影只显示在细胞的底部.你有什么主意吗? (3认同)

pos*_*sha 6

我使用以下代码实现了相同的目的,但是您已经将其放置在TableViewCell子类的layoutSubviews()方法中。

self.contentView.backgroundColor = [UIColor whiteColor];
self.contentView.layer.cornerRadius = 5;
self.contentView.layer.shadowOffset = CGSizeMake(1, 0);
self.contentView.layer.shadowColor = [[UIColor blackColor] CGColor];
self.contentView.layer.shadowRadius = 5;
self.contentView.layer.shadowOpacity = .25;
CGRect shadowFrame = self.contentView.layer.bounds;
CGPathRef shadowPath = [UIBezierPath bezierPathWithRect:shadowFrame].CGPath;
self.contentView.layer.shadowPath = shadowPath;
Run Code Online (Sandbox Code Playgroud)


Ash*_*rma 5

您可以尝试的另一种方法是采用UIViewin UITableViewCell。将背景颜色设置为UITableViewCell透明颜色。现在,您可以制作圆角并在 上添加阴影UIVIew。这看起来就像单元格宽度减小了,并且用户可以沿着 tableView 的边缘滚动。