gpt4 book ai didi

swift - 具有环绕和动态高度的SwiftUI HStack

转载 作者:行者123 更新时间:2023-12-03 09:17:39 36 4
gpt4 key购买 nike

我有这个 View 来显示从SwiftUI HStack with Wrap获得的多行文本标签,但是当我将其添加到VStack中时,这些标签会与下面放置的任何其他 View 重叠。
标签显示正确,但是 View 本身的高度未在VStack内部计算。
如何使此 View 使用内容的高度?

import SwiftUI

struct TestWrappedLayout: View {
@State var platforms = ["Ninetendo", "XBox", "PlayStation", "PlayStation 2", "PlayStation 3", "PlayStation 4"]

var body: some View {
GeometryReader { geometry in
self.generateContent(in: geometry)
}
}

private func generateContent(in g: GeometryProxy) -> some View {
var width = CGFloat.zero
var height = CGFloat.zero

return ZStack(alignment: .topLeading) {
ForEach(self.platforms, id: \.self) { platform in
self.item(for: platform)
.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 platform == self.platforms.last! {
width = 0 //last item
} else {
width -= d.width
}
return result
})
.alignmentGuide(.top, computeValue: {d in
let result = height
if platform == self.platforms.last! {
height = 0 // last item
}
return result
})
}
}
}

func item(for text: String) -> some View {
Text(text)
.padding(.all, 5)
.font(.body)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(5)
}
}

struct TestWrappedLayout_Previews: PreviewProvider {
static var previews: some View {
TestWrappedLayout()
}
}

示例代码:
struct ExampleTagsView: View {
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Platforms:")
TestWrappedLayout()

Text("Other Platforms:")
TestWrappedLayout()
}
}
}
}

struct ExampleTagsView_Previews: PreviewProvider {
static var previews: some View {
ExampleTagsView()
}
}

结果:
enter image description here

最佳答案

好的,这是一个更通用且经过改进的变体(对于SwiftUI HStack with Wrap中最初引入的解决方案)

经过Xcode 11.4/iOS 13.4测试

注意:由于 View 高度是动态计算的,因此结果在运行时有效,而不是在预览中有效

enter image description here

struct TagCloudView: View {
var tags: [String]

@State private var totalHeight
= CGFloat.zero // << variant for ScrollView/List
// = CGFloat.infinity // << variant for VStack

var body: some View {
VStack {
GeometryReader { geometry in
self.generateContent(in: geometry)
}
}
.frame(height: totalHeight)// << variant for ScrollView/List
//.frame(maxHeight: totalHeight) // << variant for VStack
}

private func generateContent(in g: GeometryProxy) -> some View {
var width = CGFloat.zero
var height = CGFloat.zero

return ZStack(alignment: .topLeading) {
ForEach(self.tags, id: \.self) { tag in
self.item(for: tag)
.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 == self.tags.last! {
width = 0 //last item
} else {
width -= d.width
}
return result
})
.alignmentGuide(.top, computeValue: {d in
let result = height
if tag == self.tags.last! {
height = 0 // last item
}
return result
})
}
}.background(viewHeightReader($totalHeight))
}

private func item(for text: String) -> some View {
Text(text)
.padding(.all, 5)
.font(.body)
.background(Color.blue)
.foregroundColor(Color.white)
.cornerRadius(5)
}

private func viewHeightReader(_ binding: Binding<CGFloat>) -> some View {
return GeometryReader { geometry -> Color in
let rect = geometry.frame(in: .local)
DispatchQueue.main.async {
binding.wrappedValue = rect.size.height
}
return .clear
}
}
}

struct TestTagCloudView : View {
var body: some View {
VStack {
Text("Header").font(.largeTitle)
TagCloudView(tags: ["Ninetendo", "XBox", "PlayStation", "PlayStation 2", "PlayStation 3", "PlayStation 4"])
Text("Some other text")
Divider()
Text("Some other cloud")
TagCloudView(tags: ["Apple", "Google", "Amazon", "Microsoft", "Oracle", "Facebook"])
}
}
}

关于swift - 具有环绕和动态高度的SwiftUI HStack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62102647/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com