Skip to content

Instantly share code, notes, and snippets.

@intellitour
Created August 6, 2021 00:59
Show Gist options
  • Save intellitour/8819099bf5f1d65c4a8ca1ab092cf57d to your computer and use it in GitHub Desktop.
Save intellitour/8819099bf5f1d65c4a8ca1ab092cf57d to your computer and use it in GitHub Desktop.
struct GridLayout {
private(set) var size: CGSize
private(set) var rowCount: Int = 0
private(set) var columnCount: Int = 0
init(itemCount: Int, nearAspectRatio desiredAspectRatio: Double = 1, in size: CGSize) {
self.size = size
guard size.width != 0, size.height != 0, itemCount > 0 else { return }
var bestLayout: (rowCount: Int, columnCount: Int) = (1, itemCount)
var smallestVariance: Double?
let sizeAspectRatio = abs(Double(size.width/size.height))
for rows in 1...itemCount {
let columns = (itemCount / rows) + (itemCount % rows > 0 ? 1 : 0)
if (rows - 1) * columns < itemCount {
let itemAspectRatio = sizeAspectRatio * (Double(rows)/Double(columns))
let variance = abs(itemAspectRatio - desiredAspectRatio)
if smallestVariance == nil || variance < smallestVariance! {
smallestVariance = variance
bestLayout = (rowCount: rows, columnCount: columns)
}
}
}
rowCount = bestLayout.rowCount
columnCount = bestLayout.columnCount
}
var itemSize: CGSize {
if rowCount == 0 || columnCount == 0 {
return CGSize.zero
} else {
return CGSize(
width: size.width / CGFloat(columnCount),
height: size.height / CGFloat(rowCount)
)
}
}
func location(ofItemAt index: Int) -> CGPoint {
if rowCount == 0 || columnCount == 0 {
return CGPoint.zero
} else {
return CGPoint(
x: (CGFloat(index % columnCount) + 0.5) * itemSize.width,
y: (CGFloat(index / columnCount) + 0.5) * itemSize.height
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment