-
-
Save adriencog/9baf1489d507ff282ecbdc29d61e2b78 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class SwipeCell: UITableViewCell { | |
var scrollView: UIScrollView! | |
var containerView: UIView! | |
var actionView: UIView! | |
let minOffset: CGFloat = 30 | |
var isLeftSideVisible:Bool { | |
return scrollView.contentOffset.x < 0 | |
} | |
var isRightSideVisible:Bool { | |
return scrollView.contentOffset.x > 0 | |
} | |
var actionLabel: UILabel! | |
var selectedAction: SwipeAction? | |
var leftActions: [SwipeAction] = [] | |
var rightActions: [SwipeAction] = [] | |
override init(style: UITableViewCellStyle, reuseIdentifier: String?) { | |
super.init(style: style, reuseIdentifier: reuseIdentifier) | |
setup() | |
} | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
setup() | |
} | |
override func setHighlighted(_ highlighted: Bool, animated: Bool) {} | |
override func setSelected(_ selected: Bool, animated: Bool) {} | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
scrollView.contentInset = UIEdgeInsets(top: 0, left: bounds.width, bottom: 0, right: bounds.width) | |
scrollView.contentSize = contentView.bounds.size | |
} | |
func setup() { | |
scrollView = UIScrollView(frame: bounds) | |
scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
scrollView.contentSize = bounds.size | |
scrollView.contentInset = UIEdgeInsets(top: 0, left: bounds.width, bottom: 0, right: bounds.width) | |
scrollView.delegate = self | |
scrollView.showsVerticalScrollIndicator = false | |
scrollView.showsHorizontalScrollIndicator = false | |
scrollView.decelerationRate = UIScrollViewDecelerationRateFast | |
contentView.addSubview(scrollView) | |
actionView = UIView(frame: CGRect(origin: .zero, size: bounds.size)) | |
actionView.backgroundColor = UIColor.gray | |
actionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
scrollView.addSubview(actionView) | |
containerView = UIView(frame: scrollView.bounds) | |
containerView.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
containerView.backgroundColor = UIColor.white | |
scrollView.addSubview(containerView) | |
actionLabel = UILabel(frame: CGRect(x: 10, y: 0, width: bounds.width - 20, height: bounds.height)) | |
actionLabel.font = UIFont.systemFont(ofSize: 12) | |
actionLabel.autoresizingMask = [.flexibleWidth, .flexibleHeight] | |
actionLabel.textColor = .white | |
actionLabel.baselineAdjustment = .alignCenters | |
actionLabel.adjustsFontSizeToFitWidth = true | |
actionView.addSubview(actionLabel) | |
} | |
func findVisibleAction() -> SwipeAction? { | |
let offsetX = abs(scrollView.contentOffset.x) | |
let actionsWidth = scrollView.contentSize.width - minOffset | |
if offsetX < minOffset { | |
return nil | |
} | |
if isLeftSideVisible { | |
let actionOffset = actionsWidth / CGFloat(leftActions.count) | |
let i = max(0, Int((offsetX - minOffset) / actionOffset)) | |
return i < leftActions.count ? leftActions[i] : nil | |
} | |
if isRightSideVisible { | |
let actionOffset = actionsWidth / CGFloat(rightActions.count) | |
let i = max(0, Int((offsetX - minOffset) / actionOffset)) | |
return i < rightActions.count ? rightActions[i] : nil | |
} | |
return nil | |
} | |
func performAction() { | |
dismissAction() | |
} | |
func dismissAction() { | |
selectedAction = nil | |
scrollView.setContentOffset(.zero, animated: false) | |
} | |
} | |
extension SwipeCell : UIScrollViewDelegate { | |
func scrollViewDidScroll(_ scrollView: UIScrollView) { | |
let offsetX = scrollView.contentOffset.x | |
actionView.frame = CGRect(origin: CGPoint(x: offsetX, y: 0), size: actionView.frame.size) | |
let action = selectedAction ?? findVisibleAction() | |
actionView.backgroundColor = action?.color ?? UIColor.lightGray | |
actionLabel.textAlignment = isRightSideVisible ? .right : .left | |
actionLabel.text = action?.title | |
} | |
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { | |
let offsetX = abs(scrollView.contentOffset.x) | |
let width = scrollView.contentSize.width | |
if offsetX < minOffset { | |
targetContentOffset.pointee = .zero | |
}else{ | |
if isLeftSideVisible { targetContentOffset.pointee.x = -width } | |
else if isRightSideVisible { targetContentOffset.pointee.x = width } | |
} | |
selectedAction = findVisibleAction() | |
} | |
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { | |
if selectedAction != nil { | |
performAction() | |
} else { | |
dismissAction() | |
} | |
} | |
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { | |
selectedAction = nil | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
struct CustomAction: SwipeAction { | |
var title: String | |
var color: UIColor | |
} | |
class ViewController: UITableViewController { | |
let cellIdentifier = "SwipeCell" | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
tableView.register(SwipeCell.self, forCellReuseIdentifier: cellIdentifier) | |
} | |
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
return 1 | |
} | |
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! SwipeCell | |
cell.rightActions = [ | |
CustomAction(title: "Action R1", color: UIColor.red), | |
CustomAction(title: "Action R2", color: UIColor.blue), | |
CustomAction(title: "Action R3", color: UIColor.purple) | |
] | |
cell.leftActions = [ | |
CustomAction(title: "Action L1", color: UIColor.green), | |
CustomAction(title: "Action L2", color: UIColor.orange) | |
] | |
return cell | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment