DAY 23 (Project 3, part 1)
Custom containers
SwiftUIは自動的にセルクロージャー内に暗黙の水平スタックを作成します。
import SwiftUI struct ContentView: View { var body: some View { GridStack(rows: 4, columns: 4) { row, col in Text("R\(row) C\(col)") } } } struct GridStack<Content: View>: View { let rows: Int let columns: Int let content: (Int, Int) -> Content var body: some View { VStack { ForEach(0..<rows, id: \.self) { row in HStack { ForEach(0..<self.columns, id: \.self) { column in self.content(row, column) } } } } } }
import SwiftUI struct ContentView: View { var body: some View { GridStack(rows: 4, columns: 4) { row, col in Image(systemName: "\(row * 4 + col).circle") Text("R\(row) C\(col)") } } } struct GridStack<Content: View>: View { let rows: Int let columns: Int let content: (Int, Int) -> Content init(rows: Int, columns: Int, @ViewBuilder content: @escaping (Int, Int) -> Content) { self.rows = rows self.columns = columns self.content = content } var body: some View { VStack { ForEach(0..<rows, id: \.self) { row in HStack { ForEach(0..<self.columns, id: \.self) { column in self.content(row, column) } } } } } }
SwiftUIビューの背後
struct ContentView: View { var body: some View { Text("Hello World") .background(Color.red) } } Text("Hello World") .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.red) Text("Hello World") .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.red) .edgesIgnoringSafeArea(.all)
修飾子の順序
Button("Hello World") { // do nothing } .background(Color.red) .frame(width: 200, height: 200) Button("Hello World") { print(type(of: self.body)) } .background(Color.red) .frame(width: 200, height: 200) Button("Hello World") { print(type(of: self.body)) } .frame(width: 200, height: 200) .background(Color.red) Text("Hello World") .padding() .background(Color.red) .padding() .background(Color.blue) .padding() .background(Color.green) .padding() .background(Color.yellow)
条件付き修飾子
struct ContentView: View { @State private var useRedText = false var body: some View { Button("Hello World") { // flip the Boolean between true and false self.useRedText.toggle() } .foregroundColor(useRedText ? .red : .blue) } }
プロパティとしてのビュー
struct ContentView: View { let motto1 = Text("Draco dormiens") let motto2 = Text("nunquam titillandus") var body: some View { VStack { motto1 motto2 } } } VStack { motto1 .foregroundColor(.red) motto2 .foregroundColor(.blue) } var motto1: some View { Text("Draco dormiens") }
構成を表示
struct ContentView: View { var body: some View { VStack(spacing: 10) { Text("First") .font(.largeTitle) .padding() .foregroundColor(.white) .background(Color.blue) .clipShape(Capsule()) Text("Second") .font(.largeTitle) .padding() .foregroundColor(.white) .background(Color.blue) .clipShape(Capsule()) } } } struct CapsuleText: View { var text: String var body: some View { Text(text) .font(.largeTitle) .padding() .foregroundColor(.white) .background(Color.blue) .clipShape(Capsule()) } } VStack(spacing: 10) { CapsuleText(text: "First") .foregroundColor(.white) CapsuleText(text: "Second") .foregroundColor(.yellow) }
カスタム修飾子
import SwiftUI struct ContentView: View { var body: some View { VStack(spacing:20){ Text("Hello World") .modifier(Title()) Text("Hello World") .titleStyle() } } } struct Title: ViewModifier { func body(content: Content) -> some View { content .font(.largeTitle) .foregroundColor(.white) .padding() .background(Color.blue) .clipShape(RoundedRectangle(cornerRadius: 10)) } } extension View { func titleStyle() -> some View { self.modifier(Title()) } }
import SwiftUI struct ContentView: View { var body: some View { Color.blue .frame(width: 300, height: 200) .watermarked(with: "Hacking with Swift") } } struct Watermark: ViewModifier { var text: String func body(content: Content) -> some View { ZStack(alignment: .bottomTrailing) { content Text(text) .font(.caption) .foregroundColor(.white) .padding(5) .background(Color.black) } } } extension View { func watermarked(with text: String) -> some View { self.modifier(Watermark(text: text)) } }