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

spacenation/swiftui-grid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SwiftUI Extensions

Collection of useful SwiftUI extensions and elements

Build Status

  • Grid based layouts
  • Sliders (horizontal, vertical, point)
  • Custom shapes
  • Data charts
  • Supports all apple platforms
  • SwiftUI code patterns (Styles, EnvironmentValues, ViewBuilder)
  • Active development for production apps

Open /Demo/SwiftUIExtensionsDemo.xcodeproj for more examples for iOS, macOS, watchOS and tvOS

Grid

Modular Grid

Grid(colors) { Rectangle() .foregroundColor($0) } .gridStyle( ModularGridStyle(columns: .min(100), rows: .min(100)) )

Staggered Grid

Grid(1...69, id: \.self) { index in Image("\(index)") .resizable() .scaledToFit() } .gridStyle( StaggeredGridStyle(tracks: 8, axis: .horizontal, spacing: 4) )

Tracks

Tracks setting allows you to customize grid behaviour to your specific use-case. Both Modular and Staggered grid use tracks value to calculate layout. In Modular layout both columns and rows are tracks.

public enum Tracks: Hashable { case count(Int) case fixed(CGFloat) case min(CGFloat) }
Count

Grid is split into equal fractions of size provided by a parent view.

ModularGridStyle(columns: 3, rows: 3) StaggeredGridStyle(tracks: 8)
Fixed

Item size is fixed to a specific width or height.

ModularGridStyle(columns: .fixed(100), rows: .fixed(100)) StaggeredGridStyle(tracks: .fixed(100))
Min

Autolayout respecting a min item width or height.

ModularGridStyle(columns: .min(100), rows: .min(100)) StaggeredGridStyle(tracks: .min(100))

Preferences

Get item size and position with preferences

struct CardsView: View { @State var selection: Int = 0 var body: some View { Grid(0..<100) { number in Card(title: "\(number)") .onTapGesture { self.selection = number } } .padding() .overlayPreferenceValue(GridItemBoundsPreferencesKey.self) { preferences in RoundedRectangle(cornerRadius: 16) .strokeBorder(lineWidth: 4) .foregroundColor(.white) .frame( width: preferences[self.selection].width, height: preferences[self.selection].height ) .position( x: preferences[self.selection].midX, y: preferences[self.selection].midY ) .animation(.linear) } } }

Sliders

Highly customizable sliders and tracks

Simple gradient value slider style

HSlider(value: $value, track: LinearGradient(gradient: Gradient(colors: [.red, .orange, .yellow, .green, .blue, .purple, .pink]), startPoint: .leading, endPoint: .trailing) .frame(height: 8) .cornerRadius(4) )

Multivalue track

ZStack { HTrack(value: value1, view: Capsule().foregroundColor(.red)).opacity(0.5) HTrack(value: value2, view: Capsule().foregroundColor(.blue)).opacity(0.5) HTrack(value: value3, view: Capsule().foregroundColor(.green)).opacity(0.5) } .animation(.spring()) .frame(height: 8) .background(Color.secondary.opacity(0.25))

Complex range slider style

HRangeSlider(range: $range, in: 0.0...1.0, step: 0.01, track: HRangeTrack( range: range, view: LinearGradient(gradient: Gradient(colors: [.yellow, .orange, .red]), startPoint: .leading, endPoint: .trailing), mask: Rectangle(), configuration: .init( offsets: 32 ) ) .background(Color.secondary.opacity(0.25)) .cornerRadius(16) .padding(.vertical, 8) .animation(.easeInOut(duration: 0.5)), lowerThumb: Capsule() .foregroundColor(.white), upperThumb: Capsule() .foregroundColor(.white), configuration: .init( thumbSize: CGSize(width: 32, height: 64), thumbInteractiveSize: CGSize(width: 44, height: 64) ), onEditingChanged: { print($0) } ) .frame(height: 64)

Complex point slider style

XYSlider(x: $x, y: $y, track: RoundedRectangle(cornerRadius: 24) .foregroundColor( Color(hue: 0.67, saturation: y, brightness: 1.0) ), thumb: ZStack { Capsule().frame(width: 12).foregroundColor(.white) Capsule().frame(height: 12).foregroundColor(.white) } .compositingGroup() .rotationEffect(Angle(radians: x * 10)) .shadow(radius: 3), configuration: .init( options: .interactiveTrack, thumbSize: CGSize(width: 48, height: 48) ) ) .frame(height: 256) .shadow(radius: 3) .padding()

Chart

Build custom charts with SwiftUI

Line Chart

Chart(data: [0.1, 0.3, 0.2, 0.5, 0.4, 0.9, 0.1]) .chartStyle( LineChartStyle(.quadCurve, lineColor: .blue, lineWidth: 5) )

Area Chart

Chart(data: [0.1, 0.3, 0.2, 0.5, 0.4, 0.9, 0.1]) .chartStyle( AreaChartStyle(.quadCurve, fill: LinearGradient(gradient: .init(colors: [Color.blue.opacity(0.2), Color.blue.opacity(0.05)]), startPoint: .top, endPoint: .bottom) ) )

Stacked Area Chart

Chart(data: matrix) .chartStyle( StackedAreaChartStyle(.quadCurve, colors: [.yellow, .orange, .red]) )

Column Chart

Chart(data: [0.1, 0.3, 0.2, 0.5, 0.4, 0.9, 0.1]) .chartStyle( ColumnChartStyle(column: Capsule().foregroundColor(.green), spacing: 2) )

Stacked Column Chart

Chart(data: matrix) .chartStyle( StackedColumnChartStyle(spacing: 2, colors: [.yellow, .orange, .red]) )

Shapes

Regular Polygons

Pentagon() Hexagon() RegularPolygon(sides: 32)

Lines and Curves

QuadCurve(unitPoints: [ UnitPoint(x: 0.1, y: 0.1), UnitPoint(x: 0.5, y: 0.9), UnitPoint(x: 0.9, y: 0.1) ]) .stroke(Color.blue, style: .init(lineWidth: 2, lineCap: .round)) .frame(height: 200)

Patterns

GridPattern(horizontalLines: 20, verticalLines: 40) .stroke(Color.white.opacity(0.3), style: .init(lineWidth: 1, lineCap: .round)) .frame(height: 200) .background(Color.blue) .padding()

SDKs

  • iOS 13+
  • Mac Catalyst 13.0+
  • macOS 10.15+
  • watchOS 6+
  • Xcode 11.0+

Roadmap

  • Animations
  • 'CSS Grid'-like features for Modular Grid
  • View Modifiers
  • Rounded regular polygons
  • Bar chart style

Code Contibutions

Feel free to contribute via fork/pull request to master branch. If you want to request a feature or report a bug please start a new issue.

Coffee Contibutions

If you find this project useful please consider becoming a sponsor.

Sponsor this project

 

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages