Skip to content

Commit

Permalink
Masonry layouts now only take one axis of alignment.
Browse files Browse the repository at this point in the history
SmartScrollView flicker bug fixed
AnyFULayoutExample updated
SmartScrollViewExample updated
  • Loading branch information
ryanlintott committed Sep 15, 2022
1 parent a2bf05e commit ac6a39f
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 23 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ MyFULayout().forEach(["Hello", "World"], id: \.self) { item in
HMasonry(columns: 3, maxHeight: height) {
ForEach(["Hello", "World", "More Text"], id: \.self) { item in
Text(item.value)
.frame(maxHeight: .infinity, alignment: .center)
.padding(12)
.foregroundColor(.white)
.background(Color.blue)
Expand All @@ -255,6 +256,7 @@ MyFULayout().forEach(["Hello", "World"], id: \.self) { item in
VMasonry(columns: 3, maxWidth: width) {
ForEach(["Hello", "World", "More Text"], id: \.self) { item in
Text(item.value)
.frame(maxWidth: .infinity, alignment: .center)
.padding(12)
.foregroundColor(.white)
.background(Color.blue)
Expand Down
13 changes: 6 additions & 7 deletions Sources/FrameUp/FULayout/Layouts/HMasonry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,25 @@ import SwiftUI
public struct HMasonry: FULayout {
typealias Row = FULayoutRow

public let alignment: Alignment
public let alignment: HorizontalAlignment
public let rows: Int
public let rowHeight: CGFloat
public let maxItemHeight: CGFloat?
public let horizontalSpacing: CGFloat
public let verticalSpacing: CGFloat

public var maxItemHeight: CGFloat? { rowHeight }
public let maxItemWidth: CGFloat? = nil
public let fixedSize: Axis.Set = .horizontal

/// Creates a FrameUp layout that arranges views into rows, adding views to the shortest row.
/// - Parameters:
/// - alignment: Used to align views vertically in their rows and align rows horizontally relative to each other. Default is leading.
/// - alignment: Used to align rows horizontally relative to each other. Default is leading.
/// - rows: Number of rows to place views in.
/// - maxHeight: Maximum height containing all rows (can be obtained through a `HeightReader`).
/// - horizontalSpacing: Minimum horizontal spacing between columns.
/// - verticalSpacing: Vertical spacing between views in a column
public init(
alignment: Alignment = .leading,
alignment: HorizontalAlignment = .leading,
rows: Int,
maxHeight: CGFloat,
horizontalSpacing: CGFloat? = nil,
Expand All @@ -61,13 +61,12 @@ public struct HMasonry: FULayout {
self.rows = max(1, rows)
self.horizontalSpacing = horizontalSpacing ?? 10
self.verticalSpacing = verticalSpacing ?? 10
self.maxItemHeight = (maxHeight - (self.horizontalSpacing * CGFloat(self.rows - 1))) / CGFloat(self.rows)
self.rowHeight = maxItemHeight ?? maxHeight
self.rowHeight = (maxHeight - (self.horizontalSpacing * CGFloat(self.rows - 1))) / CGFloat(self.rows)
}

public func contentOffsets(sizes: [Int: CGSize]) -> [Int: CGPoint] {
var rows: [Row] = (0..<rows).map { _ in
Row(alignment: alignment, spacing: verticalSpacing, height: rowHeight)
Row(alignment: Alignment(horizontal: alignment, vertical: .top), spacing: verticalSpacing, height: rowHeight)
}

for size in sizes.sortedByKey() {
Expand Down
15 changes: 7 additions & 8 deletions Sources/FrameUp/FULayout/Layouts/VMasonry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,25 @@ import SwiftUI
public struct VMasonry: FULayout {
typealias Column = FULayoutColumn

public let alignment: Alignment
public let alignment: VerticalAlignment
public let columns: Int
public let columnWidth: CGFloat
public let maxItemWidth: CGFloat?
public let horizontalSpacing: CGFloat
public let verticalSpacing: CGFloat

public var maxItemWidth: CGFloat? { columnWidth }
public let maxItemHeight: CGFloat? = nil
public let fixedSize: Axis.Set = .vertical

/// Creates a FrameUp layout that arranges views columns, adding views to the shortest column.
/// - Parameters:
/// - alignment: Used to align views horizontally in their columns and align columns vertically relative to each other. Default is top.
/// - alignment: Used to align columns vertically relative to each other. Default is top.
/// - columns: Number of columns to place views in.
/// - maxWidth: Maximum width containing all columns (can be obtained through a `WidthReader`).
/// - horizontalSpacing: Minimum horizontal spacing between columns.
/// - verticalSpacing: Vertical spacing between views in a column
public init(
alignment: Alignment = .top,
alignment: VerticalAlignment = .top,
columns: Int,
maxWidth: CGFloat,
horizontalSpacing: CGFloat? = nil,
Expand All @@ -61,13 +61,12 @@ public struct VMasonry: FULayout {
self.columns = max(1, columns)
self.horizontalSpacing = horizontalSpacing ?? 10
self.verticalSpacing = verticalSpacing ?? 10
self.maxItemWidth = (maxWidth - (self.horizontalSpacing * CGFloat(self.columns - 1))) / CGFloat(self.columns)
self.columnWidth = maxItemWidth ?? maxWidth
self.columnWidth = (maxWidth - (self.horizontalSpacing * CGFloat(self.columns - 1))) / CGFloat(self.columns)
}

public func contentOffsets(sizes: [Int: CGSize]) -> [Int: CGPoint] {
var columns: [Column] = (0..<columns).map { _ in
Column(alignment: alignment, spacing: verticalSpacing, width: columnWidth)
Column(alignment: Alignment(horizontal: .leading, vertical: alignment), spacing: verticalSpacing, width: columnWidth)
}

for size in sizes.sortedByKey() {
Expand All @@ -86,7 +85,7 @@ public struct VMasonry: FULayout {
column
.contentOffsets(columnXOffset: currentXOffset)
.forEach { result.update(with: $0) }
currentXOffset += column.columnSize.width + horizontalSpacing
currentXOffset += columnWidth + horizontalSpacing
}

return result
Expand Down
17 changes: 9 additions & 8 deletions Sources/FrameUp/ScrollView/SmartScrollView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ public struct SmartScrollView<Content: View>: View {
guard let measurements else {
/// Settings have not been set or have for some unknown reason been set to nil
if state != nil {
Task {
// Task {
resetMeasurements()
}
// }
}
return
}
Expand All @@ -141,25 +141,25 @@ public struct SmartScrollView<Content: View>: View {

guard let state else {
/// State is nil so initialize state
Task {
// Task {
self.state = .init(content: contentSize, scrollView: scrollViewSize)
}
// }
return
}

guard state.content.equals(contentSize, precision: 0.01) else {
/// Content size has changed so reset state.
Task {
// Task {
resetMeasurements()
}
// }
return
}

guard state.scrollView.equals(scrollViewSize, precision: 0.01) else {
/// Scroll view size has changed (it can only shrink) so update state.
Task {
// Task {
self.state = .init(content: contentSize, scrollView: scrollViewSize)
}
// }
return
}

Expand All @@ -180,6 +180,7 @@ public struct SmartScrollView<Content: View>: View {
return .init(contentFrame: contentFrame, scrollViewSize: scrollViewSize)
}
.fixedSize(horizontal: axes.contains(.horizontal), vertical: axes.contains(.vertical))
// .opacity(state == nil ? 0 : 1)
}
}
/// A frame that's able to shrink the scroll view is applied only when the state is known.
Expand Down

0 comments on commit ac6a39f

Please sign in to comment.