Skip to content

Latest commit

 

History

History
410 lines (347 loc) · 7.7 KB

View Components Documentation.md

File metadata and controls

410 lines (347 loc) · 7.7 KB

View Components

Modifiers

The order matters, imagine that SwiftUI renders your view after every single modifier.

.frame(maxWidth: .infinity, maxHeight: .infinity) //Sets the size of the stack
.background(.color) //background color
.background(.ultraThinMaterial) //Vibrancy
.foregroundStyle(useRedText ? .red : .blue) //Text Color with condition

Enviorment Modifier

VStack {

}
.font(.title) //Changes the font size

Stacks

Allow spacing and allignment inside the stack

var body: some View {
    Stack {

    }
}

Vertical Stack

var body: some View {
    VStack {

    }
}

Horizontal Stack

var body: some View {
    HStack {
        
    }
}

Depth Stack

var body: some View {
    ZStack {
        
    }
}

Form

Forms are scrolling lists of static controls like text and images, but can also include user interactive controls like text fields, toggle switches, buttons, and more.

var body: some View {
    Form {
        
    }
}

List

List are lists of controls like text and images, but can also include user interactive controls like text fields, toggle switches, buttons, and more. Other then forms they can include dynamic content.

var body: some View {
    List {
        
    }
    List(0..<5) {
        Text("Dynamic row \($0)")
    }
}

Creating List content from an array:

let people = ["Finn", "Leia", "Luke", "Rey"]

var body: some View {
    List(people, id: \.self) {
        Text($0)
    }

    List {
    Text("Static Row")

    ForEach(people, id: \.self) {
        Text($0)
    }

    Text("Static Row")
    }
}

Section (Visual Chunks)

To group related items visually

Section ("Title it if you want") {
    
}
Section {
    
}

Navigation Bar

To Aaoid the form scrolling into the Dynamic Island use a navigation bar on top. Without a title there is no difference to see, but it bahaves different.

var body: some View {
    NavigationStack {
        Form {

        }
        .navigationTitle("SwiftUI")
        .navigationBarTitleDisplayMode(.inline)
    }
}

Interactive Controlls

Text (Label)

Text("Hello, world!")

Text Input

struct ContentView: View {
    @State private var name = ""

    var body: some View {
        Form {
            TextField("Enter your name", text: $name)
            Text("Hello, world!")
        }
    }
}

text: for Strings value: for numeric (Int and Double)

Picker

struct ContentView: View {
    let students = ["Harry", "Hermione", "Ron"]
    @State private var selectedStudent = "Harry"

    var body: some View {
        NavigationStack {
            Form {
                Picker("Select your student", selection: $selectedStudent) {
                    ForEach(students, id: \.self) {
                        Text($0)
                    }
                }
            }
        }
    }
}

Button

Button("Button Name", role: .destructive, action: functionName)
    .buttonStyle(.bordered) //Background color
    .buttonStyle(.borderedProminent) //Text color white, background color = role

alternative

Button("Button Name") {
    print("Now deleting…")
}

Custom Button

Button {
    print("Edit button was tapped")
} label: {
    Label("Edit", systemImage: "pencil")
        .padding()
        .foregroundStyle(.white)
        .background(.red)
}

Stepper

@State private var sleepAmount = 8.0

Stepper("\(sleepAmount.formatted()) hours", value: $sleepAmount, in: 4...12, step: 0.25)

Slider

Date Picker

@State private var wakeUp = Date.now

DatePicker("Please enter a date", selection: $wakeUp, displayedComponents: .hourAndMinute, in: Date.now... )
    .labelsHidden()

Color Frame

Color.colorName
    .frame(minWidth: 200, maxWidth: .infinity, maxHeight: 200)

alternative:

Color(red: 1, green: 0.8, blue: 0)
    .frame(minWidth: 200, maxWidth: .infinity, maxHeight: 200)

ForEach

Creates a view for each time it goes through the loop

Form {
    ForEach(0 ..< 100) {
        Text("Row \($0)")
    }
}

Color Gradient

Linear Gradient

struct ContentView: View {
    var body: some View {
        LinearGradient(stops: [
            .init(color: .white, location: 0.05),
            .init(color: .black, location: 0.95),
        ], startPoint: .top, endPoint: .bottom)
    }
}

Radial Gradient

struct ContentView: View {
    var body: some View {
        RadialGradient(colors: [.blue, .black], center: .center, startRadius: 20, endRadius: 200)
    }
}

Angular Gradient

struct ContentView: View {
    var body: some View {
        AngularGradient(colors: [.red, .yellow, .green, .blue, .purple, .red], center: .center)
    }
}

background/foreground Gradient

Text("Your content")
    .background(.red.gradient)

Alert Messages

struct ContentView: View {
    @State private var showingAlert = false

    var body: some View {
        Button("Show Alert") {
            showingAlert = true
        }
        .alert("Important message", isPresented: $showingAlert) {
            Button("OK") { }
        }
    }
}

Alternatives:

.alert("Important message", isPresented: $showingAlert) {
    Button("Delete", role: .destructive) { }
    Button("Cancel", role: .cancel) { }
}
.alert("Important message", isPresented: $showingAlert) {
    Button("OK", role: .cancel) { }
} message: {
    Text("Please read this.")
}

View composition

struct ContentView: View {
    var body: some View {
        VStack(spacing: 10) {
            Text("First")
                .font(.largeTitle)
                .padding()
                .foregroundStyle(.white)
                .background(.blue)
                .clipShape(.capsule)

            Text("Second")
                .font(.largeTitle)
                .padding()
                .foregroundStyle(.white)
                .background(.blue)
                .clipShape(.capsule)
        }
    }
}

can be changed to:

struct CapsuleText: View {
    var text: String

    var body: some View {
        Text(text)
            .font(.largeTitle)
            .padding()
            .foregroundStyle(.white)
            .background(.blue)
            .clipShape(.capsule)
    }
}

struct ContentView: View {
    var body: some View {
        VStack(spacing: 10) {
            CapsuleText(text: "First")
            CapsuleText(text: "Second")
        }
    }
}

Custom modifiers

struct Title: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.largeTitle)
            .foregroundStyle(.white)
            .padding()
            .background(.blue)
            .clipShape(.rect(cornerRadius: 10))
    }
}

When working with custom modifiers, it’s usually a smart idea to create extensions on View that make them easier to use.

extension View {
    func titleStyle() -> some View {
        modifier(Title())
    }
}

Used then:

Text("Hello World")
    .titleStyle()

Sheet

Opens a Sheet that gets opened from the Bottom and overlays the "ContentView". @Environment(\.dismiss) makes the dismiss animtion.

@Environment(\.dismiss) var dismiss

struct SecondView: View {
    var body: some View {
        Text("Second View")
        Button("Dismiss") {
            dismiss()
        }
    }
}

@State private var showingSheet = false

struct ContentView: View { 
    var body: some View {
        Button("Show Sheet") {
            showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            SecondView()
        }
    }
}