「iOS」UITableView.Style.insetGrouped样式 及 代码实现圆角cell 方案

本文介绍了iOS中UITableView.Style.insetGrouped样式的使用方法,以及如何通过代码实现圆角Cell的效果。系统方案包括设置tableView的Style为insetGrouped,但需要注意该样式适用于多个group的情况。对于iOS13以下或单个group的特殊情况,文章提供了自定义代码的实现方案,包括核心代码、cell内部处理边距和在Controller中的调用方法。

网上很少搜到 insetGrouped 的样式和用法,结合自己的项目,大概阐述一下用法,最下方包含自己实现的源码

升级iOS版本后,细心的小伙伴发现了自带的 备忘录 app的列表样式发生了更改,圆角cell算是现在比较新潮的设计,本文主要讲一下系统的实现方案和自己用代码的实现方案。

一、系统实现方案

1. insetGrouped用法

很简单,用 xib 或代码方式初始化tableView时选择Style为 insetGrouped ,样式如下:

⚠️注意点:

  1. 必须选择 insetGrouped 样式
  2. 上述样式需要多个group,如果是单个group样式或plain样式则不能实现此效果(如下图)
  3. api是iOS 13及以上才能使用

2. 单个group样式预览

了解了👆注意点后,如果有特殊情况,比如兼容iOS13及以下或单个group样式怎么处理呢?下面就给出实现方案

二、自定义代码实现方案

分为三步

1. 核心代码(可以放在BaseController里)

/// 设置cell圆角
    /// - Parameters:
    ///   - cell: cell
    ///   - indexPath: indexPath
    ///   - tableView: tableView
    ///   - needSetAlone: 是否需要单独设置每个cell都是圆角. 默认按section为单位整体设置, 如果一个section只有一个cell则全部设置圆角
    public func setCornerRadiusForSectionCell(cell: UITableViewCell, indexPath: IndexPath, tableView: UITableView, needSetAlone: Bool, cellY: CGFloat) {
        //圆角半径
        let cornerRadius:CGFloat = 10.0
        
        //下面为设置圆角操作(通过遮罩实现)
        let sectionCount = tableView.numberOfRows(inSection: indexPath.section)
        let shapeLayer = CAShapeLayer()
        cell.layer.mask = nil
        
        if needSetAlone {
            let bezierPath = UIBezierPath(roundedRect:
                cell.bounds.insetBy(dx: 0.0, dy: cellY),
                                          cornerRadius: cornerRadius)
            shapeLayer.path = bezierPath.cgPath
            cell.layer.mask = shapeLayer
        } else {
            //当前分区有多行数据时
            if sectionCount > 1 {
                switch indexPath.row {
                //如果是第一行,左上、右上角为圆角
                case 0:
                    var bounds = cell.bounds
                    bounds.origin.y += 1.0  //这样每一组首行顶部分割线不显示
                    let bezierPath = UIBezierPath(roundedRect: bounds,
                                                  byRoundingCorners: [.topLeft,.topRight],
                                                  cornerRadii: CGSize(width: cornerRadius,height: cornerRadius))
                    shapeLayer.path = bezierPath.cgPath
                    cell.layer.mask = shapeLayer
                //如果是最后一行,左下、右下角为圆角
                case sectionCount - 1:
                    var bounds = cell.bounds
                    bounds.size.height -= 1.0  //这样每一组尾行底部分割线不显示
                    let bezierPath = UIBezierPath(roundedRect: bounds,
                                                  byRoundingCorners: [.bottomLeft,.bottomRight],
                                                  cornerRadii: CGSize(width: cornerRadius,height: cornerRadius))
                    shapeLayer.path = bezierPath.cgPath
                    cell.layer.mask = shapeLayer
                default:
                    break
                }
            }
                //当前分区只有一行行数据时
            else {
                //四个角都为圆角(同样设置偏移隐藏首、尾分隔线)
                let bezierPath = UIBezierPath(roundedRect:
                    cell.bounds.insetBy(dx: 0.0, dy: cellY),
                                              cornerRadius: cornerRadius)
                shapeLayer.path = bezierPath.cgPath
                cell.layer.mask = shapeLayer
            }
        }
    }

2. cell 内部处理左右边距

需要这步的原因是:
(1)需要左右边距
(2)如果只对布局做修改后,点击cell时阴影还是矩形,效果不好

override var frame: CGRect {
        didSet {
            var newFrame = frame
            newFrame.origin.x += 10
            newFrame.size.width -= 20
            super.frame = newFrame
        }
    }

3. Controller里调用

调用的位置我是放在了 willDisplay 的方法中

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        self.setCornerRadiusForSectionCell(cell: cell, indexPath: indexPath, tableView: tableView, needSetAlone: true, cellY: 10.0)
    }

以上,算不上是最优解决方案,但是也算实现了UI的要求😆

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值