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))
}
}