티스토리 뷰
반응형
import SwiftUI
/// 컨텐츠 크기 만큼 아래로 배치 되는 레이아웃 iOS 16+
struct FlowLayout: Layout {
var spacing: CGFloat? = nil
struct Cache {
var sizes: [CGSize] = []
var spacing: [CGFloat] = []
}
func makeCache(subviews: Subviews) -> Cache {
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
let spacing: [CGFloat] = subviews.indices.map { index in
guard index != subviews.count - 1 else {
return 0
}
return subviews[index].spacing.distance(
to: subviews[index+1].spacing,
along: .horizontal
)
}
return Cache(sizes: sizes, spacing: spacing)
}
func sizeThatFits(
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Cache
) -> CGSize {
var totalHeight = 0.0
var totalWidth = 0.0
var lineWidth = 0.0
var lineHeight = 0.0
for index in subviews.indices {
if lineWidth + cache.sizes[index].width > proposal.width ?? 0 {
totalHeight += lineHeight
lineWidth = cache.sizes[index].width
lineHeight = cache.sizes[index].height
} else {
lineWidth += cache.sizes[index].width + (spacing ?? cache.spacing[index])
lineHeight = max(lineHeight, cache.sizes[index].height)
}
totalWidth = max(totalWidth, lineWidth)
}
totalHeight += lineHeight
return .init(width: totalWidth, height: totalHeight)
}
func placeSubviews(
in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout Cache
) {
var lineX = bounds.minX
var lineY = bounds.minY
var lineHeight: CGFloat = 0
for index in subviews.indices {
if lineX + cache.sizes[index].width > (proposal.width ?? 0) {
lineY += lineHeight
lineHeight = 0
lineX = bounds.minX
}
let position = CGPoint(
x: lineX + cache.sizes[index].width / 2,
y: lineY + cache.sizes[index].height / 2
)
lineHeight = max(lineHeight, cache.sizes[index].height)
lineX += cache.sizes[index].width + (spacing ?? cache.spacing[index])
subviews[index].place(
at: position,
anchor: .center,
proposal: ProposedViewSize(cache.sizes[index])
)
}
}
}
struct ContentView: View {
let array = "다중 레이아웃을 사용하면 다양한 방식으로 뷰를 구성할 수 있습니다. 한 가지 중요한 것은 콘크리트 레이아웃의 하위 항목 사이의 간격입니다. 이번 주에 우리는 뷰 사이의 특정 간격을 지정할 수 있는 사용자 정의 레이아웃을 구축하는 방법과 SwiftUI에서 플랫폼 중심의 사전 정의된 간격 규칙을 준수하는 방법을 배울 것입니다.".split(separator: " ")
var body: some View {
VStack {
FlowLayout(spacing: 10) {
ForEach(array.indices, id: \.self) {
Text(array[$0])
.font($0.isMultiple(of: 2) ? .title : .title2)
.border(Color.red)
.padding(.bottom, 10) // FlowLayout 에서 줄 간격 설정 방법을 못 찾아서 이렇게 추가
}
}
}
}
}
출처
https://swiftwithmajid.com/2022/11/16/building-custom-layout-in-swiftui-basics
https://swiftwithmajid.com/2022/12/06/building-custom-layout-in-swiftui-spacing
iOS
Swift
Xcode
반응형
'iOS SwiftUI' 카테고리의 다른 글
iOS SwiftUI PageControl 페이지 컨트롤 (0) | 2024.03.01 |
---|---|
iOS SwiftUI TabView 의 tabItem 누를 때 탭 전환 대신, 네비게이션 이동 (0) | 2024.01.01 |
댓글