.testFrame()
用來測試一個 view 的 bound ( child's actual size) 與 frame (proposed size from parent) 之間的關係。
Last updated
用來測試一個 view 的 bound ( child's actual size) 與 frame (proposed size from parent) 之間的關係。
Last updated
注意:這是一個 🅿️ ViewModifier❗
/*
* Thinking is SwiftUI
* - Ch. 4, Layout
*
* ⭐️ Required: 📦 FrameBehavior
*/
import SwiftUI
// 🌀View + .testFrame()
extension View {
/// ## Examples:
/// - `view.testFrame()`
/// - `view.testFrame(frameColor: .yellow)`
/// - Parameters:
/// - boundColor: bound's border color
/// - frameColor: frame's border color
/// - maxWidth : frame's max width
/// - maxHeight : frame's max height
/// - showGrids : if `true`, show grid lines in the background
public func testFrame(
boundColor: Color = .blue,
frameColor: Color = .pink,
maxWidth : CGFloat = 400,
maxHeight : CGFloat = 400,
showGrids : Bool = true
) -> some View {
self.modifier(
FrameBehavior( // 📦 FrameBehavior
boundColor: boundColor,
frameColor: frameColor,
maxWidth : maxWidth,
maxHeight : maxHeight,
showGrids : showGrids
)
)
}
}
/*
* Thinking is SwiftUI
* - Ch. 4, Layout
*
* ⭐️ Required:
* - 🌀View + .if, .frame, .border, .grids
*/
import SwiftUI
// 📦 FrameBehavior
public struct FrameBehavior: ViewModifier {
// ⭐️ ViewModifier 的好處就是可以
// 幫原來的 view 加上新的 states
@State private var width : CGFloat = 200
@State private var height: CGFloat = 100
@State private var selection = 2 // choose horizontal alignment
// max valus for sliders
let boundColor: Color
let frameColor: Color
let maxWidth : CGFloat // max value for sliders
let maxHeight : CGFloat
let showGrids : Bool
// to align the content
var alignment: HorizontalAlignment {
switch selection {
case 1 : return .leading
case 3 : return .trailing
default: return .center
}
}
// init
public init(
boundColor: Color = .blue,
frameColor: Color = .pink,
maxWidth : CGFloat = 400,
maxHeight : CGFloat = 400,
showGrids : Bool = true
) {
self.boundColor = boundColor
self.frameColor = frameColor
self.maxWidth = maxWidth
self.maxHeight = maxHeight
self.showGrids = showGrids
}
public func body(content: Content) -> some View {
VStack {
// content to investigate
VStack(alignment: alignment) {
content
.border(4, boundColor) // content's border: 🌀View+.border
.frame(width, height) // 🌀View + .frame
.border(2, frameColor, dash: [8]) // frame's border
Rectangle().frame(height: 1).foregroundColor(.orange)
Spacer()
} // VStack
.frame(maxWidth: .infinity)
.if(showGrids){ $0.grids() } // 🌀View + .if, .grids
// sliders
VStack {
HStack {
Text("\(Int(width))")
Spacer()
Slider(value: $width , in: 0...maxWidth).frame(width: 400)
}
HStack {
Text("\(Int(height))")
Spacer()
Slider(value: $height, in: 0...maxHeight).frame(width: 400)
}
Picker("", selection: $selection) {
Text(".leading" ).tag(1)
Text(".center" ).tag(2)
Text(".trailing").tag(3)
} // Picker (Segmented Control)
.pickerStyle(SegmentedPickerStyle())
.cornerRadius(8)
.padding(.horizontal)
}.padding().background(Color(white: 0.15))
} // VStack (container)
}
}
HStack {
Text("Hello, World")
Rectangle()
.fill(Color.purple)
.frame(minWidth: 200)
}.testFrame(frameColor: .yellow) // 🌀View + .testFrame()
used to test Frame bebaviors.