SwipeTransitionLayout.swift 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. //
  2. // SwipeTransitionLayout.swift
  3. //
  4. // Created by Jeremy Koch
  5. // Copyright © 2017 Jeremy Koch. All rights reserved.
  6. //
  7. import UIKit
  8. // MARK: - Layout Protocol
  9. protocol SwipeTransitionLayout {
  10. func container(view: UIView, didChangeVisibleWidthWithContext context: ActionsViewLayoutContext)
  11. func layout(view: UIView, atIndex index: Int, with context: ActionsViewLayoutContext)
  12. func visibleWidthsForViews(with context: ActionsViewLayoutContext) -> [CGFloat]
  13. }
  14. // MARK: - Layout Context
  15. struct ActionsViewLayoutContext {
  16. let numberOfActions: Int
  17. let orientation: SwipeActionsOrientation
  18. let contentSize: CGSize
  19. let visibleWidth: CGFloat
  20. let minimumButtonWidth: CGFloat
  21. init(numberOfActions: Int, orientation: SwipeActionsOrientation, contentSize: CGSize = .zero, visibleWidth: CGFloat = 0, minimumButtonWidth: CGFloat = 0) {
  22. self.numberOfActions = numberOfActions
  23. self.orientation = orientation
  24. self.contentSize = contentSize
  25. self.visibleWidth = visibleWidth
  26. self.minimumButtonWidth = minimumButtonWidth
  27. }
  28. static func newContext(for actionsView: SwipeActionsView) -> ActionsViewLayoutContext {
  29. return ActionsViewLayoutContext(numberOfActions: actionsView.actions.count,
  30. orientation: actionsView.orientation,
  31. contentSize: actionsView.contentSize,
  32. visibleWidth: actionsView.visibleWidth,
  33. minimumButtonWidth: actionsView.minimumButtonWidth)
  34. }
  35. }
  36. // MARK: - Supported Layout Implementations
  37. class BorderTransitionLayout: SwipeTransitionLayout {
  38. func container(view: UIView, didChangeVisibleWidthWithContext context: ActionsViewLayoutContext) {
  39. }
  40. func layout(view: UIView, atIndex index: Int, with context: ActionsViewLayoutContext) {
  41. let diff = context.visibleWidth - context.contentSize.width
  42. view.frame.origin.x = (CGFloat(index) * context.contentSize.width / CGFloat(context.numberOfActions) + diff) * context.orientation.scale
  43. }
  44. func visibleWidthsForViews(with context: ActionsViewLayoutContext) -> [CGFloat] {
  45. let diff = context.visibleWidth - context.contentSize.width
  46. let visibleWidth = context.contentSize.width / CGFloat(context.numberOfActions) + diff
  47. // visible widths are all the same regardless of the action view position
  48. return (0..<context.numberOfActions).map({ _ in visibleWidth })
  49. }
  50. }
  51. class DragTransitionLayout: SwipeTransitionLayout {
  52. func container(view: UIView, didChangeVisibleWidthWithContext context: ActionsViewLayoutContext) {
  53. view.bounds.origin.x = (context.contentSize.width - context.visibleWidth) * context.orientation.scale
  54. }
  55. func layout(view: UIView, atIndex index: Int, with context: ActionsViewLayoutContext) {
  56. view.frame.origin.x = (CGFloat(index) * context.minimumButtonWidth) * context.orientation.scale
  57. }
  58. func visibleWidthsForViews(with context: ActionsViewLayoutContext) -> [CGFloat] {
  59. return (0..<context.numberOfActions)
  60. .map({ max(0, min(context.minimumButtonWidth, context.visibleWidth - (CGFloat($0) * context.minimumButtonWidth))) })
  61. }
  62. }
  63. class RevealTransitionLayout: DragTransitionLayout {
  64. override func container(view: UIView, didChangeVisibleWidthWithContext context: ActionsViewLayoutContext) {
  65. let width = context.minimumButtonWidth * CGFloat(context.numberOfActions)
  66. view.bounds.origin.x = (width - context.visibleWidth) * context.orientation.scale
  67. }
  68. override func visibleWidthsForViews(with context: ActionsViewLayoutContext) -> [CGFloat] {
  69. return super.visibleWidthsForViews(with: context).reversed()
  70. }
  71. }