✨TestIdealSizeView
⬆️ 需要: .shadowedBorder()
// 2022.02.14 / (refactor)
import SwiftUI
/// a view to test frame's (min/ideal/max) behaviors.
struct TestIdealSizeView: View {
// view state
@State private var width: CGFloat = 50 // offered width
@State private var fixed = false // fixed at ideal width
// computed property
var intWidth: Int { Int(width) } // integral width
var body: some View {
HStack(alignment: .top) {
// subviews with explicitly offered width
VStack {
subviewsWithOfferdWidth
controls
}
// subviews without explicitly offered width
VStack {
childviews.padding()
}
}
}
}
extension TestIdealSizeView {
/// subviews to test frame's behaviors.
var subviewsWithOfferdWidth: some View {
childviews
// ⭐️ parent's offered size
.frame(width: width)
// ⭐️ show frame's border
.shadowedBorder(.white.opacity(0.8)) // 🌀View+.shadowedBorder()
.padding()
}
/// child views
var childviews: some View {
Group {
// ⭐️ subviews with `idealWidth` undefined.
IdealWidthView(minWidth: 100)
IdealWidthView(minWidth: 100, maxWidth: 200)
// ⭐️ subviews with defined `idealWidth`
Group {
IdealWidthView(idealWidth: 150, color: .orange)
IdealWidthView(minWidth: 100, idealWidth: 150, color: .orange)
}
// ------------------------------------------------------
// ⭐️ fixed at ideal width?
.fixedSize(horizontal: fixed, vertical: false)
// ------------------------------------------------------
}
.frame(height: 50)
}
/// controls to change view states
var controls: some View {
VStack(spacing: 20) {
// 🎛 `Toggle` to switch on `fixed` state.
Toggle(isOn: $fixed.animation()) { // toggle with animation
Text("fixed ideal width").fixedSize() // text no wrap
.foregroundColor(.primary)
}
// 🎛 `Slider` to control the offered width
Slider(value: $width, in: 20...300, step: 1)
// label for offered width
Text("offered width: \(intWidth)")
.font(.system(.caption, design: .monospaced))
.foregroundColor(.secondary)
}
.padding()
}
}
/// ⭐️ adaptive view that can declare its min/ideal/max width.
struct IdealWidthView: View {
var minWidth: CGFloat?
var idealWidth: CGFloat?
var maxWidth: CGFloat?
var label: String {
var strs = [String]()
if let min = minWidth { strs.append("min: \(Int(min))") }
if let ideal = idealWidth { strs.append("ideal: \(Int(ideal))") }
if let max = maxWidth { strs.append("max: \(Int(max))") }
return strs.joined(separator: ", ")
}
var color: Color = .yellow
var body: some View {
color
// ------------------------------------------------------
// ⭐️ declare min/ideal/max width
.frame(minWidth: minWidth, idealWidth: idealWidth, maxWidth: maxWidth)
// ------------------------------------------------------
.overlay {
Text(label).font(.caption).fixedSize() // ⭐️ no wrap
.shadow(radius: 2)
.foregroundColor(.black)
}
// ⭐️ show frame visually
.dimension(arrow: .blue, label: .orange) // 🌀 View+.dimension()
}
}
struct TestIdealSizeView_Previews: PreviewProvider {
static var previews: some View {
TestIdealSizeView()
}
}
History
2022.02.14
Last updated
Was this helpful?