Skip to content

Instantly share code, notes, and snippets.

@Tiagoperes
Created April 20, 2022 12:37
Show Gist options
  • Save Tiagoperes/02cb138c716153da2881ab219b9efa64 to your computer and use it in GitHub Desktop.
Save Tiagoperes/02cb138c716153da2881ab219b9efa64 to your computer and use it in GitHub Desktop.
Layout examples in SwfitUI
//
// ContentView.swift
// layout-tests
//
// Created by Tiago Peres França on 15/04/22.
//
import SwiftUI
struct Example1: View {
var body: some View {
HStack(alignment: .top, spacing: 0) {
HStack() { Text("R") }
.frame(maxWidth: .infinity, maxHeight: 80, alignment: .topLeading)
.background(Color.red)
HStack() { Text("G") }
.frame(maxWidth: .infinity, maxHeight: 50, alignment: .topLeading)
.background(Color.green)
HStack() { Text("B") }
.frame(maxWidth: .infinity, maxHeight: 50, alignment: .topLeading)
.background(Color.blue)
}
.frame(maxWidth: .infinity)
.background(Color.gray)
}
}
struct Example2: View {
var body: some View {
HStack(spacing: 0) {
HStack() { Text("R") }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.background(Color.red)
.padding(.leading, 10)
HStack() { Text("G") }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.background(Color.green)
.padding(.leading, 10)
HStack() { Text("B") }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.background(Color.blue)
.padding(.leading, 10)
}
.frame(maxWidth: .infinity, maxHeight: 50)
.background(Color.gray)
}
}
struct Example3: View {
var body: some View {
HStack(spacing: 0) {
HStack() { Text("R") }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.padding(.leading, 10)
.background(Color.red)
HStack() { Text("G") }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.padding(.leading, 10)
.background(Color.green)
HStack() { Text("B") }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.padding(.leading, 10)
.background(Color.blue)
}
.frame(maxWidth: .infinity, maxHeight: 50)
.background(Color.gray)
}
}
struct Example4: View {
var body: some View {
let flexSum = 4.0
GeometryReader { geo in
HStack(spacing: 0) {
HStack() { Text("R") }
.frame(maxWidth: 2 * geo.size.width / flexSum, maxHeight: .infinity, alignment: .leading)
.background(Color.red)
HStack() { Text("G") }
.frame(maxWidth: geo.size.width / flexSum, maxHeight: .infinity, alignment: .leading)
.background(Color.green)
HStack() { Text("B") }
.frame(maxWidth: geo.size.width / flexSum, maxHeight: .infinity, alignment: .leading)
.background(Color.blue)
}
.frame(maxWidth: .infinity, maxHeight: 50)
.background(Color.gray)
}
}
}
struct Example5: View {
var body: some View {
HStack(alignment: .top, spacing: 0) {
HStack() { Text("R") }
.frame(maxWidth: .infinity, maxHeight: 50, alignment: .leading)
.background(Color.red)
.padding(.vertical, 10)
HStack() { Text("G") }
.frame(maxWidth: .infinity, maxHeight: 50, alignment: .leading)
.background(Color.green)
HStack() { Text("B") }
.frame(maxWidth: .infinity, maxHeight: 50, alignment: .leading)
.padding(.vertical, 10)
.background(Color.blue)
}
.frame(maxWidth: .infinity)
.background(Color.gray)
}
}
struct Example6: View {
var body: some View {
HStack(spacing: 0) {
HStack() { Text("Image") }
.frame(width: 100, height: 66)
.background(Color.red)
.padding(.trailing, 20)
HStack {}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.blue)
}
.frame(maxWidth: .infinity)
.background(Color.gray)
.fixedSize(horizontal: false, vertical: true)
}
}
struct Example7: View {
var body: some View {
ScrollView {
VStack(spacing: 0) {
VStack {
Text("flex-start")
HStack(spacing: 0) {
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
}
.frame(width: 75, height: 75, alignment: .topLeading)
.background(Color.gray)
.padding(.bottom, 10)
}
VStack {
Text("flex-end")
HStack(spacing: 0) {
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
}
.frame(width: 75, height: 75, alignment: .topTrailing)
.background(Color.gray)
.padding(.bottom, 10)
}
VStack {
Text("center")
HStack(spacing: 0) {
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
}
.frame(width: 75, height: 75, alignment: .top)
.background(Color.gray)
.padding(.bottom, 10)
}
VStack {
Text("space-around")
HStack(spacing: 0) {
Spacer(minLength: 0)
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
Spacer(minLength: 0)
Spacer(minLength: 0)
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
Spacer(minLength: 0)
}
.frame(width: 75, height: 75, alignment: .topLeading)
.background(Color.gray)
.padding(.bottom, 10)
}
VStack {
Text("space-between")
HStack(spacing: 0) {
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
Spacer()
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
}
.frame(width: 75, height: 75, alignment: .topLeading)
.background(Color.gray)
.padding(.bottom, 10)
}
VStack {
Text("space-evenly")
HStack(spacing: 0) {
Spacer()
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
Spacer()
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
Spacer()
}
.frame(width: 75, height: 75, alignment: .topLeading)
.background(Color.gray)
.padding(.bottom, 10)
}
}
}
}
}
struct Example8: View {
var body: some View {
VStack(spacing: 0) {
VStack {
Text("flex-start")
HStack(spacing: 0) {
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
}
.frame(width: 75, height: 75, alignment: .topLeading)
.background(Color.gray)
.padding(.bottom, 10)
}
VStack {
Text("flex-end")
HStack(spacing: 0) {
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
}
.frame(width: 75, height: 75, alignment: .bottomLeading)
.background(Color.gray)
.padding(.bottom, 10)
}
VStack {
Text("center")
HStack(spacing: 0) {
HStack {}
.frame(width: 25, height: 25)
.background(Color.red)
HStack {}
.frame(width: 25, height: 25)
.background(Color.blue)
}
.frame(width: 75, height: 75, alignment: .leading)
.background(Color.gray)
.padding(.bottom, 10)
}
VStack {
Text("stretch")
HStack(spacing: 0) {
HStack {}
.frame(width: 25)
.frame(maxHeight: .infinity)
.background(Color.red)
HStack {}
.frame(width: 25)
.frame(maxHeight: .infinity)
.background(Color.blue)
}
.frame(width: 75, height: 75, alignment: .topLeading)
.background(Color.gray)
.padding(.bottom, 10)
}
}
}
}
struct Example9: View {
var body: some View {
HStack(spacing: 0) {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et ipsum eu nunc semper dapibus vitae id urna. Aenean fermentum purus vitae leo congue varius vel nec ligula. Ut feugiat consectetur augue mattis tempus. Curabitur a erat nec lectus convallis vestibulum. Pellentesque suscipit id tellus ac dapibus. Vivamus aliquam, urna eu ornare euismod, arcu purus vestibulum dolor, ac tempus ante metus mollis ipsum. Ut eget tellus mollis, efficitur sapien in, pulvinar neque.")
}
.frame(width: 300)
.background(Color.gray)
}
}
struct Example10: View {
var body: some View {
HStack(spacing: 0) {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et ipsum eu nunc semper dapibus vitae id urna. Aenean fermentum purus vitae leo congue varius vel nec ligula. Ut feugiat consectetur augue mattis tempus. Curabitur a erat nec lectus convallis vestibulum. Pellentesque suscipit id tellus ac dapibus. Vivamus aliquam, urna eu ornare euismod, arcu purus vestibulum dolor, ac tempus ante metus mollis ipsum. Ut eget tellus mollis, efficitur sapien in, pulvinar neque.")
.fixedSize()
}
.frame(width: 300, alignment: .leading)
.clipped()
.background(Color.gray)
}
}
/* Example 11:
* https://www.fivestars.blog/articles/flexible-swiftui/
* https://github.com/dkk/WrappingHStack
*/
struct Example12: View {
var body: some View {
HStack(spacing: 0) {
HStack {}.frame(width: 50, height: 30).background(Color.red)
HStack {}.frame(width: 100, height: 30).background(Color.green)
HStack {}.frame(width: 80, height: 30).background(Color.blue)
HStack {}.frame(width: 60, height: 30).background(Color.purple)
HStack {}.frame(width: 120, height: 30).background(Color.brown)
HStack {}.frame(width: 160, height: 30).background(Color.cyan)
HStack {}.frame(width: 30, height: 30).background(Color.indigo)
HStack {}.frame(width: 300, height: 30).background(Color.mint)
HStack {}.frame(width: 150, height: 30).background(Color.orange)
HStack {}.frame(width: 130, height: 30).background(Color.pink)
// HStack {}.frame(width: 40, height: 30).background(Color.teal)
}
.frame(width: 300, alignment: .leading)
.clipped()
.background(Color.gray)
}
}
struct Example13: View {
var body: some View {
VStack {
VStack {}.frame(width: 100, height: 100).overlay(
RoundedRectangle(cornerRadius: 50)
.stroke(Color.red, lineWidth: 4)
)
// can't really make dotted
VStack {}.frame(width: 100, height: 100).overlay(
RoundedRectangle(cornerRadius: 25)
.stroke(Color.green, style: StrokeStyle(lineWidth: 6, lineCap: .butt, lineJoin: .miter, miterLimit: 0, dash: [5, 10], dashPhase: 0))
)
VStack {}.frame(width: 100, height: 100).overlay(
Rectangle()
.stroke(Color.blue, style: StrokeStyle(lineWidth: 2, dash: [5]))
)
}
}
}
struct Example14: View {
var body: some View {
VStack(alignment: .leading) {
HStack(alignment: .top, spacing: 0) {
HStack {}
.frame(width: 30, height: 200)
.background(Color.red)
HStack {}
.frame(width: 200, height: 30)
.background(Color.blue)
}
.frame(width: 100, height: 100, alignment: .topLeading)
.background(Color.gray)
Text("This text goes after the example, the content should overflow on top of this.")
}
}
}
struct Example15: View {
var body: some View {
ZStack(alignment: .topLeading) {
HStack {}
.frame(width: 50, height: 50)
.background(Color.red)
.offset(x: 0, y: 0)
HStack {}
.frame(width: 50, height: 50)
.background(Color.blue)
.offset(x: 25, y: 25)
}
.frame(width: 150, height: 150, alignment: .topLeading)
.background(Color.gray)
}
}
struct Example16: View {
var body: some View {
ZStack(alignment: .topLeading) {
ZStack {
HStack {}
.frame(width: 50, height: 50)
.background(Color.red)
.offset(x: 10, y: 10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
ZStack {
HStack {}
.frame(width: 50, height: 50)
.background(Color.green)
.offset(x: -10, y: 10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
ZStack {
HStack {}
.frame(width: 50, height: 50)
.background(Color.blue)
.offset(x: -10, y: -10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
ZStack {
HStack {}
.frame(width: 50, height: 50)
.background(Color.purple)
.offset(x: 10, y: -10)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomLeading)
}
.frame(width: 150, height: 150, alignment: .topLeading)
.background(Color.gray)
}
}
struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {}
}
struct Example25: View {
private let totalFlexFactor = 3
@State private var freeSpace: CGSize? = nil
func getFlexibleWidth(parentWidth: CGFloat, factor: Int) -> CGFloat {
return (CGFloat(factor) / CGFloat(totalFlexFactor)) * (freeSpace?.width ?? 0)
}
var body: some View {
GeometryReader { parentGeometry in
VStack {
Spacer()
HStack(spacing: 0) {
HStack() { Text("Width\n= 50").font(.system(size: 12)) }
.frame(maxWidth: 50, maxHeight: .infinity)
.background(Color.red)
HStack() { Text("Flex = 2").font(.system(size: 12)) }
.frame(maxWidth: getFlexibleWidth(parentWidth: parentGeometry.size.width, factor: 2), maxHeight: .infinity)
.background(Color.green)
HStack() { Text("Width\n= 80").font(.system(size: 12)) }
.frame(maxWidth: 80, maxHeight: .infinity)
.background(Color.blue)
HStack() { Text("Flex = 1").font(.system(size: 12)) }
.frame(maxWidth: getFlexibleWidth(parentWidth: parentGeometry.size.width, factor: 1), maxHeight: .infinity)
.background(Color.purple)
if (freeSpace == nil) {
HStack() {}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(
GeometryReader { geometryProxy in
Color.clear
.preference(key: SizePreferenceKey.self, value: geometryProxy.size)
}
)
}
}
.frame(maxWidth: .infinity, maxHeight: 50)
.background(Color.gray)
.onPreferenceChange(SizePreferenceKey.self) { newSize in
if (freeSpace == nil) {
freeSpace = newSize
}
}
Spacer()
}
}
}
}
struct ContentView: View {
var body: some View {
Example4()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Example16()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment