I have a UITableView with some cells that have shadows. When I make a pan gesture to see the row actions of any cell, the table view clips the bounds of the cell until the gesture is finished.
I have clipsToBounds
set to false
on my cell's contentView
and its superview, and also for the table view.
My code for the custom cell:
var isExpanded: Bool = false
@IBOutlet weak var shadowView: UIView!
@IBOutlet weak var fullContainer: UIView!
override func awakeFromNib() {
super.awakeFromNib()
reloadUI()
}
func reloadUI() {
contentView.superview?.clipsToBounds = false
contentView.clipsToBounds = false
fullContainer.layer.masksToBounds = true
fullContainer.layer.cornerRadius = 8
shadowView.layer.masksToBounds = false
shadowView.layer.cornerRadius = 8
shadowView.layer.shadowOpacity = 1.0
shadowView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
shadowView.layer.shadowPath = UIBezierPath(roundedRect: fullContainer.bounds, cornerRadius: 8).cgPath
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
isExpanded = selected
reloadUI()
}
code for the viewcontroller with tableview:
extension SecondViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let action = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
tableView.deleteRows(at: [indexPath], with: .automatic)
}
return [action]
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.reloadRows(at: [indexPath], with: .automatic)
selectedIndex = indexPath.section
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return section != 0 ? 8 : 1
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView()
view.clipsToBounds = false
return view
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if selectedIndex == indexPath.section {
return 120
}
return 108
}
}
SecondViewController
also has this code, because it has a pan recognizer for change between view controllers with the gesture
extension SecondViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == recognizer || otherGestureRecognizer == recognizer {
return false
}
return true
}
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == recognizer{
for cell in tableView.visibleCells {
let location = gestureRecognizer.location(in: cell.contentView)
if cell.contentView.layer.contains(location) {
return false
}
}
return true
}
return true
}
}
UITableViewCell with bounds clipped:
This looks like a bug in UITableView. It can be solved with the following extension:
extension UITableView {
func fixCellBounds() {
DispatchQueue.main.async { [weak self] in
for cell in self?.visibleCells ?? [] {
cell.layer.masksToBounds = false
cell.contentView.layer.masksToBounds = false
}
}
}
}
Just call it after calling reloadRows
/insertRows
/deleteRows
etc.:
tableView.reloadRows(at: <index paths>, with: .automatic)
tableView.fixCellBounds()
Before:
After:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With