I need to develop a tableview with edit actions on rows that look similar to the ones on iOS Notification center.
The resources I have used so far, say that I can only edit the background color and width of edit actions. What I want is the custom look like that of the notifications in iOS Notifications Center.
See the annotated portion. This is what I want.
This is what I have managed so far :|
Any help / guidance would be greatly appreciated!
Thanks in advance!
I ended up creating my own views as a part of the table view cell and adding custom animation..
Sample Code:
In my tableViewController:
override func viewDidLoad() {
super.viewDidLoad()
....
let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(handleTap))
tableView.addGestureRecognizer(tapGesture)
let leftSwipeGesture = UISwipeGestureRecognizer.init(target: self, action: #selector(handleLeftSwipe(_:)))
leftSwipeGesture.direction = .left
tableView.addGestureRecognizer(leftSwipeGesture)
let rightSwipeGesture = UISwipeGestureRecognizer.init(target: self, action: #selector(handleRightSwipe(_:)))
rightSwipeGesture.direction = .right
tableView.addGestureRecognizer(rightSwipeGesture)
}
func handleTap(_ gestureRecognizer: UISwipeGestureRecognizer) {
let point = gestureRecognizer.location(in: self.tableView)
if let indexPath = self.tableView.indexPathForRow(at: point) {
var shouldSelectRow = false
if indexPathBeingEdited != nil {
if indexPath == indexPathBeingEdited {
shouldSelectRow = true
} else {
//handle close of the cell being edited already
if let previousEditedCell = tableView.cellForRow(at: indexPathBeingEdited!) as? NotificationCenterTableViewCell {
previousEditedCell.closeEditActions()
indexPathBeingEdited = nil
}
}
} else {
shouldSelectRow = true
}
if shouldSelectRow {
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .middle)
tableView(tableView, didSelectRowAt: indexPath)
}
}
}
func handleLeftSwipe(_ gestureRecognizer: UISwipeGestureRecognizer) {
let point = gestureRecognizer.location(in: self.tableView)
if let indexPath = self.tableView.indexPathForRow(at: point) {
if indexPathBeingEdited != nil {
if indexPath == indexPathBeingEdited {
//Do nothing
} else {
//handle close of the cell being edited already
if let previousEditedCell = tableView.cellForRow(at: indexPathBeingEdited!) as? NotificationCenterTableViewCell {
previousEditedCell.closeEditActions()
indexPathBeingEdited = nil
}
}
}
//proceed with left swipe action
if let cell = tableView.cellForRow(at: indexPath) as? NotificationCenterTableViewCell {
cell.handleLeftSwipe(gestureRecognizer)
let notification = notificationsArray[indexPath.section].notificationItems[indexPath.row]
//Update the title of Read button
if notification.isNotificationRead {
cell.readUnreadButtonLabel.text = "Unread"
} else {
cell.readUnreadButtonLabel.text = "Read"
}
indexPathBeingEdited = indexPath
}
}
}
func handleRightSwipe(_ gestureRecognizer: UISwipeGestureRecognizer) {
let point = gestureRecognizer.location(in: self.tableView)
if let indexPath = self.tableView.indexPathForRow(at: point) {
if indexPathBeingEdited != nil {
if indexPath == indexPathBeingEdited {
if let cell = tableView.cellForRow(at: indexPath) as? NotificationCenterTableViewCell {
cell.closeEditActions()
indexPathBeingEdited = nil
//Update the title of Read button
cell.readUnreadButtonLabel.text = "Read"
}
} else {
//handle close of the cell being edited already
if let previousEditedCell = tableView.cellForRow(at: indexPathBeingEdited!) as? NotificationCenterTableViewCell {
previousEditedCell.closeEditActions()
indexPathBeingEdited = nil
//Update the title of Read button
previousEditedCell.readUnreadButtonLabel.text = "Read"
}
}
}
}
}
In my table view cell:
func handleLeftSwipe(_ gestureRecognizer: UISwipeGestureRecognizer) {
if !isBeingEdited {
//Action to open the edit buttons
UIView.animate(withDuration: 0.5, animations: {
self.notificationHolderViewLeadingConstraint.constant -= 248
self.notificationHolderViewTrailingConstraint.constant -= 248
self.editActionsView.isHidden = false
self.layoutIfNeeded()
}, completion: { (success) in
})
isBeingEdited = true
}
}
func closeEditActions() {
if isBeingEdited {
//Action to open the edit buttons
UIView.animate(withDuration: 0.5, animations: {
self.notificationHolderViewLeadingConstraint.constant += 248
self.notificationHolderViewTrailingConstraint.constant += 248
self.editActionsView.isHidden = true
self.layoutIfNeeded()
}, completion: { (success) in
})
isBeingEdited = false
}
}
override func draw(_ rect: CGRect) {
if let viewToRound = editActionsView {
let path = UIBezierPath(roundedRect:viewToRound.bounds,
byRoundingCorners:[.topRight, .topLeft, .bottomRight, .bottomLeft],
cornerRadii: CGSize(width: 20, height: 20))
let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
viewToRound.layer.mask = maskLayer
}
}
Just FYI, I have my edit buttons i.e., Read / View / Clear added to the editActionsView. The corresponding actions are hooked up with IBActions in my tableViewCell class.
The outcome is this: