โจ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()
}
}
.shadowedBorder() - draw frame's border.
used to test Frame's ideal size behaviors.
uses Toggle to switch view state.
uses Slider to control parent's offered size.
History
2022.02.14
// 2022.02.14
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 {
VStack {
subviews
slider
}
}
}
extension TestIdealSizeView {
/// subviews to test frame's behaviors.
var subviews: some View {
Group {
// โญ๏ธ subviews with `idealWidth` undefined.
IdealWidthView(minWidth: 100)
IdealWidthView(minWidth: 100, maxWidth: 200)
// โญ๏ธ subviews with defined `idealWidth`
Group {
IdealWidthView(idealWidth: 150)
IdealWidthView(minWidth: 100, idealWidth: 150)
}
// โญ๏ธ fixed at ideal width?
.fixedSize(horizontal: fixed, vertical: false)
.overlay {
// ๐ `Toggle` to switch on `fixed` state.
Toggle(isOn: $fixed.animation()) { // toggle with animation
Text("fixed").fixedSize() // text no wrap
.foregroundColor(.primary)
}
.frame(width: 100, alignment: .trailing)
.offset(x: 60 + width/2)
}
}
// โญ๏ธ parent's offered size
.frame(width: width, height: 50)
// โญ๏ธ show frame's border
.shadowedBorder(.white.opacity(0.8)) // ๐View+.shadowedBorder()
.padding()
}
/// slider to control the offered width
var slider: some View {
VStack(spacing: 20) {
VStack {
// ๐ `Slider` control
Slider(value: $width, in: 20...300, step: 1)
.padding(.horizontal)
Text("offered width: \(intWidth)")
.font(.system(.caption, design: .monospaced))
.foregroundColor(.secondary)
}
}
.padding()
}
}
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 {
// โญ๏ธ adpative view that may have min/ideal/max width
color
// โญ๏ธ define min/ideal/max width
.frame(minWidth: minWidth, idealWidth: idealWidth, maxWidth: maxWidth)
.overlay {
Text(label).font(.caption).fixedSize() // โญ๏ธ no wrap
.foregroundColor(.black)
}
// โญ๏ธ show frame visually
.dimension(arrow: .blue, label: .orange) // ๐ View+.dimension()
}
}
struct TestIdealSizeView_Previews: PreviewProvider {
static var previews: some View {
TestIdealSizeView()
}
}
Last updated