Skip to content

Commit

Permalink
Merge pull request #98 from Shopify/corner-layouts
Browse files Browse the repository at this point in the history
Support for edges of a cell
  • Loading branch information
raulriera authored May 26, 2018
2 parents 74ed0ed + 97b2682 commit f25bf30
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 91 deletions.
87 changes: 80 additions & 7 deletions FunctionalTableData/TableItemLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,117 @@ public protocol TableItemLayout {

// TableItemLayout

public typealias EdgeBasedTableItemLayout = CombinedLayout<EdgeLayout.Horizontal, EdgeLayout.Vertical>
public typealias LayoutMarginsTableItemLayout = CombinedLayout<MarginsLayout.Horizontal, MarginsLayout.Vertical>
public typealias EdgeBasedTableItemLayout = Layout<EdgeLayout.Top, EdgeLayout.Leading, EdgeLayout.Bottom, EdgeLayout.Trailing>
public typealias LayoutMarginsTableItemLayout = Layout<MarginsLayout.Top, MarginsLayout.Leading, MarginsLayout.Bottom, MarginsLayout.Trailing>

public struct ExplicitLayoutMarginsTableItemLayout: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
contentView.preservesSuperviewLayoutMargins = false
view.constrainToFillView(contentView, respectingLayoutMargins: true)

MarginsLayout.Top.layoutView(view, inContentView: contentView)
MarginsLayout.Leading.layoutView(view, inContentView: contentView)
MarginsLayout.Bottom.layoutView(view, inContentView: contentView)
MarginsLayout.Trailing.layoutView(view, inContentView: contentView)
}
}

public enum EdgeLayout {
@available(*, deprecated, message: "Use `EdgeLayout.Leading` and `EdgeLayout.Trailing` instead.")
public struct Horizontal: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
view.constrainToFillViewHorizontally(contentView)
Leading.layoutView(view, inContentView: contentView)
Trailing.layoutView(view, inContentView: contentView)
}
}

@available(*, deprecated, message: "Use `EdgeLayout.Top` and `EdgeLayout.Bottom` instead.")
public struct Vertical: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
view.constrainToFillViewVertically(contentView)
Top.layoutView(view, inContentView: contentView)
Bottom.layoutView(view, inContentView: contentView)
}
}

public struct Top: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
view.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
}
}

public struct Leading: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
}
}

public struct Bottom: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
contentView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}

public struct Trailing: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
contentView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
}
}
}

public enum MarginsLayout {
@available(*, deprecated, message: "Use `MarginsLayout.Leading` and `MarginsLayout.Trailing` instead.")
public struct Horizontal: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
view.constrainToFillViewHorizontally(contentView, respectingLayoutMargins: true)
Leading.layoutView(view, inContentView: contentView)
Trailing.layoutView(view, inContentView: contentView)
}
}

@available(*, deprecated, message: "Use `MarginsLayout.Top` and `MarginsLayout.Bottom` instead.")
public struct Vertical: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
view.constrainToFillViewVertically(contentView, respectingLayoutMargins: true)
Top.layoutView(view, inContentView: contentView)
Bottom.layoutView(view, inContentView: contentView)
}
}

public struct Top: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
view.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor).isActive = true
}
}

public struct Leading: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
view.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor).isActive = true
}
}

public struct Bottom: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
contentView.layoutMarginsGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}

public struct Trailing: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
contentView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
}
}
}

@available(*, deprecated, message: "Use `Layout<Top:Leading:Bottom:Trailing>` instead.")
public struct CombinedLayout<Horizontal: TableItemLayout, Vertical: TableItemLayout>: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
Horizontal.layoutView(view, inContentView: contentView)
Vertical.layoutView(view, inContentView: contentView)
}
}

public struct Layout<Top: TableItemLayout, Leading: TableItemLayout, Bottom: TableItemLayout, Trailing: TableItemLayout>: TableItemLayout {
public static func layoutView(_ view: UIView, inContentView contentView: UIView) {
Top.layoutView(view, inContentView: contentView)
Leading.layoutView(view, inContentView: contentView)
Bottom.layoutView(view, inContentView: contentView)
Trailing.layoutView(view, inContentView: contentView)
}
}
84 changes: 0 additions & 84 deletions FunctionalTableData/UIView+AutoLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,88 +15,4 @@ extension UIView {
addSubview(view)
}
}

func constraintsToFillView(_ otherView: UIView, respectingLayoutMargins: Bool = false) -> [NSLayoutConstraint] {
return constraintsToFillViewHorizontally(otherView, respectingLayoutMargins: respectingLayoutMargins) + constraintsToFillViewVertically(otherView, respectingLayoutMargins: respectingLayoutMargins)
}

func constraintsToFillView(_ otherView: UIView, insetBy margins: UIEdgeInsets, respectingLayoutMargins: Bool = false) -> [NSLayoutConstraint] {

if respectingLayoutMargins {
let layoutMarginsGuide = otherView.layoutMarginsGuide

return [
topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: margins.top),
bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor, constant: -margins.bottom),
leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor, constant: margins.left),
trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor, constant: -margins.right)
]
} else {
return [
topAnchor.constraint(equalTo: otherView.topAnchor, constant: margins.top),
bottomAnchor.constraint(equalTo: otherView.bottomAnchor, constant: -margins.bottom),
leadingAnchor.constraint(equalTo: otherView.leadingAnchor, constant: margins.left),
trailingAnchor.constraint(equalTo: otherView.trailingAnchor, constant: -margins.right)
]
}
}

func constraintsToFillViewVertically(_ otherView: UIView, respectingLayoutMargins: Bool = false) -> [NSLayoutConstraint] {
if respectingLayoutMargins {
let layoutMarginsGuide = otherView.layoutMarginsGuide

return [
topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor),
bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor)
]
} else {
return [
topAnchor.constraint(equalTo: otherView.topAnchor),
bottomAnchor.constraint(equalTo: otherView.bottomAnchor)
]
}
}

func constraintsToFillViewHorizontally(_ otherView: UIView, respectingLayoutMargins: Bool = false) -> [NSLayoutConstraint] {
if respectingLayoutMargins {
let layoutMarginsGuide = otherView.layoutMarginsGuide

return [
leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor)
]
} else {
return [
leadingAnchor.constraint(equalTo: otherView.leadingAnchor),
trailingAnchor.constraint(equalTo: otherView.trailingAnchor)
]
}
}

func constraintsToBeCenteredInView(_ otherView: UIView) -> [NSLayoutConstraint] {
return [
centerXAnchor.constraint(equalTo: otherView.centerXAnchor),
centerYAnchor.constraint(equalTo: otherView.centerYAnchor)
]
}

func constrainToFillView(_ otherView: UIView, respectingLayoutMargins: Bool = false) {
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(constraintsToFillView(otherView, respectingLayoutMargins: respectingLayoutMargins))
}

func constrainToFillViewVertically(_ otherView: UIView, respectingLayoutMargins: Bool = false) {
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(constraintsToFillViewVertically(otherView, respectingLayoutMargins: respectingLayoutMargins))
}

func constrainToFillViewHorizontally(_ otherView: UIView, respectingLayoutMargins: Bool = false) {
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(constraintsToFillViewHorizontally(otherView, respectingLayoutMargins: respectingLayoutMargins))
}

func constrainToBeCenteredInView(_ otherView: UIView) {
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate(constraintsToBeCenteredInView(otherView))
}
}

0 comments on commit f25bf30

Please sign in to comment.