Skip to content
This repository has been archived by the owner on Dec 27, 2020. It is now read-only.

Commit

Permalink
More examples (#91)
Browse files Browse the repository at this point in the history
* sectioned grid ios

* layout and examples
  • Loading branch information
ay42 authored Mar 29, 2020
1 parent 1f9807e commit 50c14fa
Show file tree
Hide file tree
Showing 17 changed files with 345 additions and 47 deletions.
14 changes: 14 additions & 0 deletions GridDemo iOS/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ struct ContentView: View {
Text("Staggered Grid")
}
}

NavigationLink(destination: SectionedGridView()) {
HStack {
Image(systemName: "rectangle.grid.1x2.fill")
Text("Sectioned Grid")
}
}

NavigationLink(destination: StaticGridView()) {
HStack {
Image(systemName: "circle.grid.2x2.fill")
Text("Static Grid")
}
}
}
}
.listStyle(
Expand Down
58 changes: 58 additions & 0 deletions GridDemo iOS/SectionedGrid/SectionedGridView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import SwiftUI
import Grid

struct SectionedGridView: View {
var body: some View {
ScrollView {
ForEach(1..<8) { section in
Section {
HStack {
Text("Section \(section)").font(.headline).fontWeight(.bold)
Spacer()
}

Grid(self.rangeFor(section: section), id: \.self) { index in
Rectangle()
.foregroundColor(.clear)
.background(
Image("\(index)")
.renderingMode(.original)
.resizable()
.scaledToFill()
)
.clipped()
.clipShape(RoundedRectangle(cornerRadius: 4))
}

Spacer(minLength: 16)
}
}

.padding(8)
}
.navigationBarTitle("Sectioned Grid", displayMode: .inline)
.gridStyle(
ModularGridStyle(columns: .min(80), rows: .fixed(80), spacing: 4)
)
}

private func rangeFor(section: Int) -> Range<Int> {
switch section {
case 1: return Range(1...10)
case 2: return Range(11...15)
case 3: return Range(16...26)
case 4: return Range(27...35)
case 5: return Range(36...38)
case 6: return Range(39...55)
case 7: return Range(56...69)
default:
fatalError()
}
}
}

struct SectionedGridView_Previews: PreviewProvider {
static var previews: some View {
SectionedGridView()
}
}
33 changes: 33 additions & 0 deletions GridDemo iOS/StaticGrid/StaticGridView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import SwiftUI
import Grid

struct StaticGridView: View {
var body: some View {
ScrollView {
Grid {
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
}
.padding(16)
.frame(height: 300)
}
.navigationBarTitle("Static Grid", displayMode: .inline)
.gridStyle(
ModularGridStyle(columns: 5, rows: 2, spacing: 16)
)
}
}

struct StaticGridView_Previews: PreviewProvider {
static var previews: some View {
StaticGridView()
}
}
4 changes: 4 additions & 0 deletions GridDemo macOS/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ struct ContentView: View {
NavigationLink(destination: SectionedGridView()) {
Text("Sectioned Grid")
}

NavigationLink(destination: StaticGridView()) {
Text("Static Grid")
}
}
}
.frame(minWidth: 200, maxWidth: 300)
Expand Down
32 changes: 32 additions & 0 deletions GridDemo macOS/StaticGrid/StaticGridView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import SwiftUI
import Grid

struct StaticGridView: View {
var body: some View {
ScrollView {
Grid {
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
Capsule().foregroundColor(.random)
}
.padding(16)
.frame(height: 300)
}
.gridStyle(
ModularGridStyle(columns: 5, rows: 2, spacing: 16)
)
}
}

struct StaticGridView_Previews: PreviewProvider {
static var previews: some View {
StaticGridView()
}
}
48 changes: 42 additions & 6 deletions GridDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

/* Begin PBXBuildFile section */
FA6203C323F8AD77009CB0C9 /* Grid in Frameworks */ = {isa = PBXBuildFile; productRef = FA6203C223F8AD77009CB0C9 /* Grid */; };
FA9FFB6D242FFECD0047D145 /* SectionedGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA9FFB6C242FFECD0047D145 /* SectionedGrid.swift */; };
FA9FFB6D242FFECD0047D145 /* SectionedGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA9FFB6C242FFECD0047D145 /* SectionedGridView.swift */; };
FA9FFB70243005B80047D145 /* SectionedGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA9FFB6F243005B80047D145 /* SectionedGridView.swift */; };
FA9FFB74243008060047D145 /* StaticGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA9FFB73243008060047D145 /* StaticGridView.swift */; };
FAA2C96C23DEAECC00FBDE39 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAA2C96B23DEAECC00FBDE39 /* SceneDelegate.swift */; };
FAA2C96E23DEAECC00FBDE39 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAA2C96D23DEAECC00FBDE39 /* ContentView.swift */; };
FAA2C97623DEAECD00FBDE39 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FAA2C97423DEAECD00FBDE39 /* LaunchScreen.storyboard */; };
Expand Down Expand Up @@ -66,6 +68,7 @@
FAA2CA5523DEB66A00FBDE39 /* StaggeredGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAA2CA5323DEB66900FBDE39 /* StaggeredGridView.swift */; };
FAA2CA5923DEB73200FBDE39 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = FAA2CA5823DEB73200FBDE39 /* README.md */; };
FAAA2FCD241C42E4007021F7 /* ImageDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAA2FCC241C42E4007021F7 /* ImageDetailView.swift */; };
FAC1C78B2430694C00FFA885 /* StaticGridView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC1C78A2430694C00FFA885 /* StaticGridView.swift */; };
FAC9D4DE23DF8CE20007B7DD /* Grid in Frameworks */ = {isa = PBXBuildFile; productRef = FAC9D4DD23DF8CE20007B7DD /* Grid */; };
FAC9D4E023DF8CE90007B7DD /* Grid in Frameworks */ = {isa = PBXBuildFile; productRef = FAC9D4DF23DF8CE90007B7DD /* Grid */; };
FAC9D4E223DF8CEE0007B7DD /* Grid in Frameworks */ = {isa = PBXBuildFile; productRef = FAC9D4E123DF8CEE0007B7DD /* Grid */; };
Expand Down Expand Up @@ -114,7 +117,9 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
FA9FFB6C242FFECD0047D145 /* SectionedGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionedGrid.swift; sourceTree = "<group>"; };
FA9FFB6C242FFECD0047D145 /* SectionedGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionedGridView.swift; sourceTree = "<group>"; };
FA9FFB6F243005B80047D145 /* SectionedGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionedGridView.swift; sourceTree = "<group>"; };
FA9FFB73243008060047D145 /* StaticGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticGridView.swift; sourceTree = "<group>"; };
FAA2C96723DEAECC00FBDE39 /* GridDemo iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "GridDemo iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
FAA2C96B23DEAECC00FBDE39 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
FAA2C96D23DEAECC00FBDE39 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -171,7 +176,8 @@
FAA2CA5323DEB66900FBDE39 /* StaggeredGridView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StaggeredGridView.swift; sourceTree = "<group>"; };
FAA2CA5823DEB73200FBDE39 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
FAAA2FCC241C42E4007021F7 /* ImageDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageDetailView.swift; sourceTree = "<group>"; };
FAC9D4DC23DF8C750007B7DD /* */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ""; sourceTree = SOURCE_ROOT; };
FAC1C7882430682100FFA885 /* swiftui-grid */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "swiftui-grid"; sourceTree = "<group>"; };
FAC1C78A2430694C00FFA885 /* StaticGridView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticGridView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -213,11 +219,27 @@
FA9FFB6B242FFE510047D145 /* SectionedGrid */ = {
isa = PBXGroup;
children = (
FA9FFB6C242FFECD0047D145 /* SectionedGrid.swift */,
FA9FFB6C242FFECD0047D145 /* SectionedGridView.swift */,
);
path = SectionedGrid;
sourceTree = "<group>";
};
FA9FFB6E2430057F0047D145 /* SectionedGrid */ = {
isa = PBXGroup;
children = (
FA9FFB6F243005B80047D145 /* SectionedGridView.swift */,
);
path = SectionedGrid;
sourceTree = "<group>";
};
FA9FFB72243007EA0047D145 /* StaticGrid */ = {
isa = PBXGroup;
children = (
FA9FFB73243008060047D145 /* StaticGridView.swift */,
);
path = StaticGrid;
sourceTree = "<group>";
};
FAA2C93B23DEAD2600FBDE39 = {
isa = PBXGroup;
children = (
Expand All @@ -230,7 +252,7 @@
FAA2CA3B23DEB64800FBDE39 /* GridDemo tvOS */,
FAA2C94923DEAE7B00FBDE39 /* Products */,
FAA2C99423DEB0A700FBDE39 /* Frameworks */,
FAC9D4DC23DF8C750007B7DD /* */,
FAC1C7882430682100FFA885 /* swiftui-grid */,
);
sourceTree = "<group>";
};
Expand All @@ -250,6 +272,8 @@
FAA2C96823DEAECC00FBDE39 /* GridDemo iOS */ = {
isa = PBXGroup;
children = (
FAC1C7892430693900FFA885 /* StaticGrid */,
FA9FFB6E2430057F0047D145 /* SectionedGrid */,
FAA2C98823DEB00100FBDE39 /* ModularGrid */,
FAA2C98B23DEB00100FBDE39 /* StaggeredGrid */,
FAA2C97B23DEAF9200FBDE39 /* AppDelegate.swift */,
Expand Down Expand Up @@ -311,6 +335,7 @@
FAA2C99D23DEB26200FBDE39 /* GridDemo macOS */ = {
isa = PBXGroup;
children = (
FA9FFB72243007EA0047D145 /* StaticGrid */,
FA9FFB6B242FFE510047D145 /* SectionedGrid */,
FAA2C9B323DEB31800FBDE39 /* ModularGrid */,
FAA2C9B623DEB31800FBDE39 /* StaggeredGrid */,
Expand Down Expand Up @@ -442,6 +467,14 @@
path = StaggeredGrid;
sourceTree = "<group>";
};
FAC1C7892430693900FFA885 /* StaticGrid */ = {
isa = PBXGroup;
children = (
FAC1C78A2430694C00FFA885 /* StaticGridView.swift */,
);
path = StaticGrid;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
Expand Down Expand Up @@ -683,6 +716,7 @@
buildActionMask = 2147483647;
files = (
FAA2C98523DEAFF100FBDE39 /* Item.swift in Sources */,
FA9FFB70243005B80047D145 /* SectionedGridView.swift in Sources */,
FAA2C99123DEB00100FBDE39 /* StaggeredGridView.swift in Sources */,
FAA2C99023DEB00100FBDE39 /* StaggeredGridSettingsView.swift in Sources */,
FAAA2FCD241C42E4007021F7 /* ImageDetailView.swift in Sources */,
Expand All @@ -693,14 +727,16 @@
FAA2C96E23DEAECC00FBDE39 /* ContentView.swift in Sources */,
FAA2C98F23DEB00100FBDE39 /* ModularGridSettingsView.swift in Sources */,
FAA2C98E23DEB00100FBDE39 /* ModularGridView.swift in Sources */,
FAC1C78B2430694C00FFA885 /* StaticGridView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FAA2C99823DEB26200FBDE39 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FA9FFB6D242FFECD0047D145 /* SectionedGrid.swift in Sources */,
FA9FFB6D242FFECD0047D145 /* SectionedGridView.swift in Sources */,
FA9FFB74243008060047D145 /* StaticGridView.swift in Sources */,
FAA2C9B023DEB26B00FBDE39 /* Item.swift in Sources */,
FAA2C9AF23DEB26B00FBDE39 /* Color+Random.swift in Sources */,
FAA2C9BB23DEB31900FBDE39 /* StaggeredGridSettingsView.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 SwiftExtensions.
Copyright (c) 2020 SpaceNation Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ SwiftUI Grid view layout with custom styles.
## Features
- ZStack based layout
- Vertical and horizontal scrolling
- Supports grid of grids, each with it's own style
- Supports all apple platforms
- Custom styles (ModularGridStyle, StaggeredGridStyle)
- SwiftUI code patterns (StyleStructs, EnvironmentValues, ViewBuilder)
Expand Down
16 changes: 8 additions & 8 deletions Sources/Grid/Grid.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SwiftUI
/// A view that arranges its children in a grid.
public struct Grid<Content>: View where Content: View {
@Environment(\.gridStyle) private var style
@State var preferences: GridPreferences = .init(items: [])
@State var preferences: GridPreferences = GridPreferences(size: .zero, items: [])
let items: [GridItem]

public var body: some View {
Expand All @@ -15,8 +15,8 @@ public struct Grid<Content>: View where Content: View {
width: self.style.autoWidth ? self.preferences[item.id]?.bounds.width : nil,
height: self.style.autoHeight ? self.preferences[item.id]?.bounds.height : nil
)
.alignmentGuide(.leading, computeValue: { _ in self.preferences[item.id]?.bounds.origin.x ?? 0 })
.alignmentGuide(.top, computeValue: { _ in self.preferences[item.id]?.bounds.origin.y ?? 0 })
.alignmentGuide(.leading, computeValue: { _ in geometry.size.width - (self.preferences[item.id]?.bounds.origin.x ?? 0) })
.alignmentGuide(.top, computeValue: { _ in geometry.size.height - (self.preferences[item.id]?.bounds.origin.y ?? 0) })
.background(GridPreferencesModifier(id: item.id, bounds: self.preferences[item.id]?.bounds ?? .zero))
.anchorPreference(key: GridItemBoundsPreferencesKey.self, value: .bounds) { [geometry[$0]] }
}
Expand All @@ -25,14 +25,14 @@ public struct Grid<Content>: View where Content: View {
self.style.transform(preferences: &$0, in: geometry.size)
}
}
.onPreferenceChange(GridPreferencesKey.self) { preferences in
self.preferences = preferences
}
.frame(
width: self.style.axis == .horizontal ? self.preferences.size.width : nil,
height: self.style.axis == .vertical ? self.preferences.size.height : nil,
minWidth: self.style.axis == .horizontal ? self.preferences.size.width : nil,
minHeight: self.style.axis == .vertical ? self.preferences.size.height : nil,
alignment: .topLeading
)
.onPreferenceChange(GridPreferencesKey.self) { preferences in
self.preferences = preferences
}
}
}

Expand Down
18 changes: 9 additions & 9 deletions Sources/Grid/Styles/ModularGridStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,34 +42,34 @@ public struct ModularGridStyle: GridStyle {
)
)

preferences.items = layoutPreferences(
preferences = layoutPreferences(
tracks: computedTracksCount,
spacing: self.spacing,
axis: self.axis,
itemSize: itemSize,
preferences: preferences.items
preferences: preferences
)
}

private func layoutPreferences(tracks: Int, spacing: CGFloat, axis: Axis, itemSize: CGSize, preferences: [GridPreferences.Item]) -> [GridPreferences.Item] {
private func layoutPreferences(tracks: Int, spacing: CGFloat, axis: Axis, itemSize: CGSize, preferences: GridPreferences) -> GridPreferences {
var tracksLengths = Array(repeating: CGFloat(0.0), count: tracks)
var newPreferences: [GridPreferences.Item] = []
var newPreferences: GridPreferences = GridPreferences(items: [])

preferences.forEach { preference in
preferences.items.forEach { preference in
if let minValue = tracksLengths.min(), let indexMin = tracksLengths.firstIndex(of: minValue) {
let itemSizeWidth = itemSize.width
let itemSizeHeight = itemSize.height
let width = axis == .vertical ? itemSizeWidth * CGFloat(indexMin) + CGFloat(indexMin) * spacing : tracksLengths[indexMin]
let height = axis == .vertical ? tracksLengths[indexMin] : itemSizeHeight * CGFloat(indexMin) + CGFloat(indexMin) * spacing

let origin = CGPoint(x: 0 - width, y: 0 - height)
let origin = CGPoint(x: width, y: height)
tracksLengths[indexMin] += (axis == .vertical ? itemSizeHeight : itemSizeWidth) + spacing

newPreferences.append(
GridPreferences.Item(
newPreferences.merge(with:
GridPreferences(items: [GridPreferences.Item(
id: preference.id,
bounds: CGRect(origin: origin, size: CGSize(width: itemSizeWidth, height: itemSizeHeight))
)
)])
)
}
}
Expand Down
Loading

0 comments on commit 50c14fa

Please sign in to comment.