Я пытаюсь сделать что-то довольно простое в моей голове.
Я хочу, чтобы подпредставление VStack динамически изменяло свою высоту в зависимости от его содержимого (ProblematicView в примере ниже).
Обычно это работает довольно хорошо, но в этом случае ProblematicView содержит GeometryReader (для имитации HStack в несколько строк).
Однако GeometryReader с жадностью занимает все пространство, которое может (ожидаемое поведение происходит если вы удалите GeometryReader и его содержимое). К сожалению, в родительском представлении (UmbrellaView в приведенном ниже примере) UmbrellaView VStack назначает 50% себя для ProblematicView вместо минимального размера для отображения содержимого представления.
Я потратил несколько часов играть с аргументами min / ideal / maxHeight frame, но безрезультатно.
Реально ли то, что я пытаюсь достичь?
Я добавил картинки внизу, чтобы уточнить визуально.
struct UmbrellaView: View {
var body: some View {
VStack(spacing: 0) {
ProblematicView()
.background(Color.blue)
ScrollView(.vertical) {
Group {
Text("A little bit about this").font(.system(size: 20))
Divider()
}
Group {
Text("some").font(.system(size: 20))
Divider()
}
Group {
Text("group").font(.system(size: 20)).padding(.bottom)
Divider()
}
Group {
Text("content").font(.system(size: 20))
}
}
}
}
}
struct ProblematicView: View {
var body: some View {
let tags: [String] = ["content", "content 2 ", "content 3"]
var width = CGFloat.zero
var height = CGFloat.zero
return VStack(alignment: .center) {
Text("Some reasonnably long text that changes dynamically do can be any size").background(Color.red)
GeometryReader { g in
ZStack(alignment: .topLeading) {
ForEach(tags, id: \.self) { tag in
TagView(content: tag, color: .red, action: {})
.padding([.horizontal, .vertical], 4)
.alignmentGuide(.leading, computeValue: { d in
if (abs(width - d.width) > g.size.width)
{
width = 0
height -= d.height
}
let result = width
if tag == tags.last! {
width = 0 //last item
} else {
width -= d.width
}
return result
})
.alignmentGuide(.top, computeValue: {d in
let result = height
if tag == tags.last! {
height = 0 // last item
}
return result
})
}
}.background(Color.green)
}.background(Color.blue)
}.background(Color.gray)
}
}
struct TagView: View {
let content: String
let color: Color
let action: () -> Void?
var body: some View {
HStack {
Text(content).padding(EdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5))
Button(action: {}) {
Image(systemName: "xmark.circle").foregroundColor(Color.gray)
}.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 7))
}
.background(color)
.cornerRadius(8.0)
}
}
struct ProblematicView_Previews: PreviewProvider {
static var previews: some View {
return ProblematicView()
}
}
struct UmbrellaView_Previews: PreviewProvider {
static var previews: some View {
return UmbrellaView()
}
}

