跨表单部分对齐视图

Posted

技术标签:

【中文标题】跨表单部分对齐视图【英文标题】:Aligning views across form sections 【发布时间】:2021-06-11 19:32:56 【问题描述】:

我正在 SwiftUI 中创建一个包含多个部分的表单。每个部分包含几个文本字段,每个字段都有一个标签。

我想将文本字段的前缘相互对齐,并与视图的中心对齐。

我可以使用以下方法在一个部分中对齐文本字段的前沿:

extension HorizontalAlignment 
    private struct LeadingEdgeAlignment: AlignmentID 
        /// A custom alignment for leading edges.
        static func defaultValue(in context: ViewDimensions) -> CGFloat 
            context[.leading]
        
    

    /// A guide for aligning leading edges.
    static let leadingEdge = HorizontalAlignment(LeadingEdgeAlignment.self)


struct ContentView: View 
    var body: some View 
        Form 
            Section(header: Text("Section One")) 
                VStack(alignment: .leadingEdge) 
                    HStack 
                        Text("Primary")
                        TextField("", text: .constant(""))
                            .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                            .alignmentGuide(.leadingEdge)  $0[HorizontalAlignment.leading] 
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                    HStack 
                        Text("Secondary")
                        TextField("", text: .constant(""))
                            .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                            .alignmentGuide(.leadingEdge)  $0[HorizontalAlignment.leading] 
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                
            
            Section(header: Text("Section Two")) 
                VStack(alignment: .leadingEdge) 
                    HStack 
                        Text("Milk")
                        TextField("", text: .constant(""))
                            .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                            .alignmentGuide(.leadingEdge)  $0[HorizontalAlignment.leading] 
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                    HStack 
                        Text("Cheesecake")
                        TextField("", text: .constant(""))
                            .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                            .alignmentGuide(.leadingEdge)  $0[HorizontalAlignment.leading] 
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                
            
        
    

但是,到目前为止,我创建跨节对齐指南的所有尝试都失败了。

如何?

【问题讨论】:

【参考方案1】:

由于您要分成两半,因此一种方法是使用偶数列。但是你必须处理文本长度的显着差异

struct AlignedSectionView: View 
    let columns = [GridItem(), GridItem()]
    var body: some View 
        Form 
            Section(header: Text("Section One")) 
                //Divide the section in half
                LazyVGrid(columns: columns, alignment: .leadingEdge) 
                    HStack 
                        Text("Primary")
                        //Push the TextField to the Halfway point
                        Spacer()
                        TextField("", text: .constant(""))
                            .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                            .alignmentGuide(.leadingEdge)  $0[HorizontalAlignment.leading] 
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                    //Fill in the column
                    Spacer()
                    HStack 
                        Text("Secondary")
                        Spacer()
                        TextField("", text: .constant(""))
                            .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                            .alignmentGuide(.leadingEdge)  $0[HorizontalAlignment.leading] 
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                
            
            Section(header: Text("Section Two")) 
                //Divide the section in half
                LazyVGrid(columns: columns, alignment: .leadingEdge) 
                    HStack 
                        Text("Milk")
                        //Push the TextField to the Halfway point
                        Spacer()
                        TextField("", text: .constant(""))
                            .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                            .alignmentGuide(.leadingEdge)  $0[HorizontalAlignment.leading] 
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                    //Fill in the column
                    Spacer()
                    HStack 
                        Text("Cheesecake")
                            //So it doesnt go to the next line
                            .lineLimit(1)
                        Spacer()
                        TextField("", text: .constant(""))
                            .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                            .alignmentGuide(.leadingEdge)  $0[HorizontalAlignment.leading] 
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                    
                
            
        
        //One way of dealing with the difference in text sizes is to allow the text to get smaller to fit
        .minimumScaleFactor(0.9)
    

【讨论】:

这让我走上了正轨,谢谢。我调整了您的代码,将标签和文本字段放在不同的列中,以获得我想要的外观。【参考方案2】:

根据lorem ipsum 的回答,我能够使用LazyVGrid 实现我想要的。

struct ContentView: View 
    let columns = [GridItem(.flexible(), alignment: .trailing), GridItem(.flexible(), alignment: .leading)]
    var body: some View 
        Form 
            Section(header: Text("Section One")) 
                LazyVGrid(columns: columns) 
                    Text("Primary")
                    TextField("", text: .constant(""))
                        .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                    Text("Secondary")
                    TextField("", text: .constant(""))
                        .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                
            
            Section(header: Text("Section Two")) 
                LazyVGrid(columns: columns) 
                    Text("Milk")
                    TextField("", text: .constant(""))
                        .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                    Text("Cheesecake")
                    TextField("", text: .constant(""))
                        .frame(minWidth: nil, idealWidth: nil, maxWidth: 75, minHeight: nil, maxHeight: nil)
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                
            
        
    

【讨论】:

以上是关于跨表单部分对齐视图的主要内容,如果未能解决你的问题,请参考以下文章

通过 AJAX 将表单发布到部分视图

在带有部分视图的 MVC 5 中将提交按钮移到表单之外

如何在该部分存在时更改该部分的标题标签文本对齐方式

通过表单将复杂类型从部分视图传递到控制器操作

5 第一个Django第4部分(表单和通用视图)

DataAnnotations 无法提交使用 ajax 调用的部分视图的表单