Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
获取并设置多个SwiftUI视图之间的最大宽度_Swift_Xcode_Swiftui - Fatal编程技术网

获取并设置多个SwiftUI视图之间的最大宽度

获取并设置多个SwiftUI视图之间的最大宽度,swift,xcode,swiftui,Swift,Xcode,Swiftui,Xcode 12.3 | SwiftUI 2.0 | Swift 5.3 我有多个HStack,它们的第一个元素必须具有相同的宽度,但我不知道如何实现这一点 HStack { Text("Label 1:") Text("Random texts") } 这将显示以下内容: Label 1: Random Texts Label 2 Other Size: Random Texts Additional Text Lab

Xcode 12.3 | SwiftUI 2.0 | Swift 5.3

我有多个
HStack
,它们的第一个元素必须具有相同的宽度,但我不知道如何实现这一点

HStack { 
    Text("Label 1:")
    Text("Random texts")
}
这将显示以下内容:

Label 1:    Random Texts
Label 2 Other Size:    Random Texts   Additional Text
Label 3 Other Larger Size:    Random Texts
我想在不使用
vstack
的情况下显示此,因为每个
HStack
都是一个
列表行

 Label 1:                      Random Texts
 Label 2 Other Size:           Random Texts   Additional Text
 Label 3 Other Larger Size:    Random Texts   
[__________________________]  [_____________...
         same size
我尝试使用一个
@propertyWrapper
来存储每个
标签背景的
GeometryProxy
,并计算最大
WrappedValue
,以设置每个
标签的
.frame(maxWidth:value)
,但如果不成功,我无法使用该属性wrapper(我遇到循环和崩溃)

可以使用标准变量(而不是@State变量)将GeometryReader宽度传递到任何子视图中

试试这段代码,它使用GeometryReader和一个可识别项列表,这些项被传递一个“labelWidth”,它们为所有标签呈现相同的宽度。注意:我在行中使用了VStack,因此它看起来更好,不明白为什么行中不能有VStack

[![struct Item : Identifiable {
    var id:UUID = UUID()
    var label:String
    var val:\[String\]
}

struct ItemRow: View {
    var labelWidth:CGFloat = 0
    var item:Item

    var body: some View {
        HStack(spacing:5) {
            Text(item.label)
                .frame(width:labelWidth, alignment: .leading)
            VStack(alignment: .leading) {
                ForEach(0 ..< item.val.indices.count) { idx in
                    Text(item.val\[idx\])
                }
            }
        }
    }
}

struct ContentView : View {
    
    @State var items:\[Item\] = \[
        Item(label:"Label 1:", val:\["Random texts"\]),
        Item(label:"Label 2 Other Size:", val:\["Random texts","Additional text"\]),
        Item(label:"Label 3 Other Larger Size:", val:\["Random texts", "Random texts and texts", "Random texts", "Random texts"\])
    \]
    
    var body: some View {
        GeometryReader { geo in
            let labelWidth = geo.size.width * 0.6 // set this however you want to calculate label width
            List(items) { item in
                ItemRow(labelWidth: labelWidth, item: item)
            }
        }
    }
}][1]][1]
[![struct Item:可识别{
变量id:UUID=UUID()
变量标签:字符串
var val:\[String\]
}
struct ItemRow:视图{
变量标签宽度:CGFloat=0
var项目:项目
var body:一些观点{
HStack(间距:5){
文本(项目标签)
.frame(宽度:labelWidth,对齐:。前导)
VStack(对齐:。前导){
ForEach(0..
您可以使用标准变量(而不是@State变量)将GeometryReader宽度传递到任何子视图中

试试这段代码,它使用GeometryReader和一个可识别项列表,这些项被传递一个“labelWidth”,它们为所有标签呈现相同的宽度。注意:我在行中使用了VStack,因此它看起来更好,不明白为什么行中不能有VStack

[![struct Item : Identifiable {
    var id:UUID = UUID()
    var label:String
    var val:\[String\]
}

struct ItemRow: View {
    var labelWidth:CGFloat = 0
    var item:Item

    var body: some View {
        HStack(spacing:5) {
            Text(item.label)
                .frame(width:labelWidth, alignment: .leading)
            VStack(alignment: .leading) {
                ForEach(0 ..< item.val.indices.count) { idx in
                    Text(item.val\[idx\])
                }
            }
        }
    }
}

struct ContentView : View {
    
    @State var items:\[Item\] = \[
        Item(label:"Label 1:", val:\["Random texts"\]),
        Item(label:"Label 2 Other Size:", val:\["Random texts","Additional text"\]),
        Item(label:"Label 3 Other Larger Size:", val:\["Random texts", "Random texts and texts", "Random texts", "Random texts"\])
    \]
    
    var body: some View {
        GeometryReader { geo in
            let labelWidth = geo.size.width * 0.6 // set this however you want to calculate label width
            List(items) { item in
                ItemRow(labelWidth: labelWidth, item: item)
            }
        }
    }
}][1]][1]
[![struct Item:可识别{
变量id:UUID=UUID()
变量标签:字符串
var val:\[String\]
}
struct ItemRow:视图{
变量标签宽度:CGFloat=0
var项目:项目
var body:一些观点{
HStack(间距:5){
文本(项目标签)
.frame(宽度:labelWidth,对齐:。前导)
VStack(对齐:。前导){
ForEach(0..
最简单的方法是为HStack中的第一个文本()设置一个特定的.frame(宽度:)。然后可以使用.minimumScaleFactor()调整其中文本的大小,以避免单词被截断。下面是一个让您开始学习的示例:

struct ContentView: View {
    var body: some View {
        VStack {
            CustomRow(title: "Label 1:", otherContent: ["Random Texts"])
            CustomRow(title: "Label 2 Other Size::", otherContent: ["Random Texts", "Additional Text",])
            CustomRow(title: "Label 3 Other Larger Size:", otherContent: ["Random Texts"])
        }
    }
    
}

struct CustomRow: View {
    
    let title: String
    let otherContent: [String]
    
    var body: some View {
        HStack {
            
            Text(title)
                .frame(width: 200, alignment: .leading)
                .lineLimit(1)
                .minimumScaleFactor(0.5)
            
            ForEach(otherContent, id: \.self) { item in
                Text(item)
                    .lineLimit(1)
                    .minimumScaleFactor(0.1)
            }
            
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }
    
}
结果:


最简单的方法是为HStack中的第一个文本()设置一个特定的.frame(宽度:)。然后可以使用.minimumScaleFactor()调整其中文本的大小,以避免单词被截断。下面是一个让您开始学习的示例:

struct ContentView: View {
    var body: some View {
        VStack {
            CustomRow(title: "Label 1:", otherContent: ["Random Texts"])
            CustomRow(title: "Label 2 Other Size::", otherContent: ["Random Texts", "Additional Text",])
            CustomRow(title: "Label 3 Other Larger Size:", otherContent: ["Random Texts"])
        }
    }
    
}

struct CustomRow: View {
    
    let title: String
    let otherContent: [String]
    
    var body: some View {
        HStack {
            
            Text(title)
                .frame(width: 200, alignment: .leading)
                .lineLimit(1)
                .minimumScaleFactor(0.5)
            
            ForEach(otherContent, id: \.self) { item in
                Text(item)
                    .lineLimit(1)
                    .minimumScaleFactor(0.1)
            }
            
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }
    
}
结果:

视图之间的平衡宽度 根据所有的回答,我编写了一个更简单的方法,用修改器来实现这一点

首先,我们必须使用视图修改器和宽度获取器添加必要的扩展:

extension View {
    
    func balanceWidth(store width: Binding<CGFloat>, alignment: HorizontalAlignment = .center) -> some View {
        modifier(BalancedWidthGetter(width: width, alignment: alignment))
    }
    
    @ViewBuilder func `if`<Transform: View>(_ condition: Bool, transform: (Self) -> Transform) -> some View {
        if condition {
            transform(self)
        } else {
            self
        }
    }
}
用法 有了这个,所有的工作都完成了。为了在视图之间获得相等的宽度,我们所要做的就是用
balancedWidth
修饰符标记每个视图,并将共享宽度值存储在
@状态
变量中,初始值==
.zero

@State var width: CGFloat = 0          <-- Initial value MUST BE == .zero

SomeView()
    .balanceWidth(store: $width)

AnotherViewRightAligned()
    .balanceWidth(store: $width, alignment: .leading)

通过创建多个
@State
变量,我们可以在视图之间创建更多关系,并分别平衡视图之间的宽度。

平衡视图之间的宽度 根据所有的回答,我编写了一个更简单的方法,用修改器来实现这一点

首先,我们必须使用视图修改器和宽度获取器添加必要的扩展:

extension View {
    
    func balanceWidth(store width: Binding<CGFloat>, alignment: HorizontalAlignment = .center) -> some View {
        modifier(BalancedWidthGetter(width: width, alignment: alignment))
    }
    
    @ViewBuilder func `if`<Transform: View>(_ condition: Bool, transform: (Self) -> Transform) -> some View {
        if condition {
            transform(self)
        } else {
            self
        }
    }
}
用法 有了这个,所有的工作都完成了。为了在视图之间获得相等的宽度,我们所要做的就是用
balancedWidth
修饰符标记每个视图,并将共享宽度值存储在
@状态
变量中,初始值==
.zero

@State var width: CGFloat = 0          <-- Initial value MUST BE == .zero

SomeView()
    .balanceWidth(store: $width)

AnotherViewRightAligned()
    .balanceWidth(store: $width, alignment: .leading)


通过创建多个
@State
变量,我们可以在视图之间创建更多关系并分别平衡它们之间的宽度。

这是否回答了您的问题?这是否回答了您的问题?
struct ContentView: View {
    
    @State var width: CGFloat = 0
    
    var body: some View {
        VStack(alignment: .leading) {
            HStack {
                Text("Label 1")
                    .balanceWidth(store: $width, alignment: .leading)
                Text("Textss")
            }
            HStack {
                Text("Label 2: more text")
                    .balanceWidth(store: $width, alignment: .leading)
                Text("Another random texts")
            }
            HStack {
                Text("Label 3: another texts")
                    .balanceWidth(store: $width, alignment: .leading)
                Text("Random texts")
            }
        }
        .padding()
    }
}