默认情况下,UITableViewCell
的选中效果如图。单独选中的效果给人的感觉不是那么可靠。
但从编程角度看,使用选中状态比较简单。不使用选中,而采用标记替代选中比较麻烦。因为这个对号是属于UITableViewCell
的accessoryType
属性。它并不是和选中状态同步的。需要单独、小心地处理,稍有不慎,就会出现各种错误。
解决思路
创建一个背景透明的对号标记
我最初的想法是创建一个背景透明的对号标记。然后把它应用在UITableViewCell
的selectedBackgroundView
属性上。
这条路不好走。因为一旦制定了selectedBackgroundView
。表格之间的分隔线就没有。解决方案有利用各种方式画分隔线的。比较麻烦。
在我采用默认的表格,并允许多选时,我发现苹果的默认选中,就是没有分割线的,只不过它用了有颜色的背景。这在单选时不明显,一旦有多选,就很明显。
创建一个有背景色的对号标记
创建好的图片如图。
用1x的语言描述,背景:宽320,高44。对号:宽16,高32,水平居中,右边距16。
难点来了
我们知道,不同格式设备的宽度是不一样的。那么对于320这个iOS设备的最小宽度,这个图片在遇到更宽的设备时是需要拉伸的。
关于如何拉伸图片,我们可以看这篇:UIImage图片拉伸平铺(resizableImage)。
看着不难,实际上全是坑。因为思维习惯不是直接的,是间接的。
简述一下拉伸图片的原理
如图,如果有一个图片,被分成1-9共9个部分。那么它的四个角的1、3、7、9图形保持不变。我们通过定义2/上、4/左、8/下、6/右的方式,来确定5的范围,然后选择拉伸5。这个就是定义图片拉伸的原理。
1 | 2 | 3 |
---|---|---|
4 | 5 | 6 |
7 | 8 | 9 |
下面应用这个原理,放大上面的带对号的背景图。
因为我们需要保证对号的位置不变,所以要把它画在3的位置。这是唯一的限制。根据这个限制我们可以计算出。
- 上:
- 上边距 = (背景高 - 对号高) / 2 = (44 - 32) / 2 = 6
- 上 = 上边距 + 对号高 = 6 + 32 = 38
- 右 = 对号宽 + 右边距 = 16 + 16 = 32
至于下和左,我们因为要尽量保证5越大越好,就都取1。
最终代码如下:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "sampleCell", for: indexPath)
// 获得背景图
let image = #imageLiteral(resourceName: "Checkmark_background")
// 指定拉伸范围
let edgeInsets = UIEdgeInsetsMake(38, 1, 1, 32)
// 获得拉伸图片
let resizableImage = image.resizableImage(withCapInsets: edgeInsets, resizingMode: .stretch)
// 生成图片视图,大小与表格项相同
let imageView = UIImageView(frame: cell.bounds)
// 指定图片
imageView.image = resizableImage
// 指定表格项选中时的背景视图
cell.selectedBackgroundView = imageView
// 设定文字
cell.textLabel?.text = "条件\(indexPath.row)"
return cell
}
最终效果
如图: