以牺牲 HStack 中相邻的 Divider 控件为代价,将 Text 控件的优先级设置得尽可能宽

Prioritising a Text control to be as wide as possible at the expense of an adjacent Divider control in a HStack

我有一个视图由 HStack 中的多个 UI 元素组成:

  1. 时间
  2. 图标
  3. 总结
  4. 分隔线
  5. 价值

我希望 1)、2) 和 5) 占用的空间不超过 space,即我不需要干预。

对于 3) 和 4) 我希望摘要尽可能多地占用 space,但要牺牲后面的分隔线。如果这意味着可以出现 none 或最小数量的分隔符,那就这样吧。然而,尽管我尽了最大的努力,摘要似乎只占用了一定数量的 space,导致其内容在多行中 运行 以确保分隔符始终出现。给它一个 layoutPriority 略有帮助。

我不想给它一个 minWidth,因为我希望根据内容动态安排宽度的分布。

代码如下:

HStack {
    
    // MARK: Time
    HStack {
        VStack {
            Spacer()
            Text("9am")
            Spacer()
        }
    }.padding(.horizontal, 4)
    .padding(.vertical)
    .background(Color.blue.opacity(0.2))
    .cornerRadius(8)
         
    VStack {
        HStack {
            
            // MARK: Icon
            Image(systemName: "cloud.drizzle.fill")
            .font(Font.title2)
            
            // MARK: Summary
            VStack {
                HStack {
                    Text("Humid and overcast")
                        .padding(.trailing, 2)
                        .background(Color.white)
                        .layoutPriority(100)
                    Spacer()
                }
            }
            
            // MARK: Line
            VStack {
                Spacer()
                Divider()
                Spacer()
            }
            
            // MARK: Values
            VStack {
                Text(String(22.66))
                Text("25%")
                    .foregroundColor(Color.black)
                    .background(Color.white)
            }
            
            Spacer()
        }
    }
}

这是它的样子:

当文本有足够的空间放在一行时,您可以将文本 运行 分到多行,只要后面的分隔线变短以容纳较长的文本即可。

固定大小在这里应该会有帮助。使用 Xcode 12.1 / iOS 14.1

测试

struct TestLongHStack: View {
    var body: some View {
        HStack {
            
            // MARK: Time
            HStack {
                VStack {
                    Spacer()
                    Text("9am")
                    Spacer()
                }
            }.padding(.horizontal, 4)
            .padding(.vertical)
            .background(Color.blue.opacity(0.2))
            .cornerRadius(8)
            
            VStack {
                HStack {
                    
                    // MARK: Icon
                    Image(systemName: "cloud.drizzle.fill")
                        .font(Font.title2)
                    
                    // MARK: Summary
                    VStack {
                        HStack {
                            Text("Humid and overcast").fixedSize()  // << here !!
                                .padding(.trailing, 2)
                                .background(Color.white)
                                .layoutPriority(100)
                            Spacer()
                        }
                    }
                    
                    // MARK: Line
                    VStack {
                        Spacer()
                        Divider()
                        Spacer()
                    }
                    
                    // MARK: Values
                    VStack {
                        Text(String(22.66)).bold().italic()
                        Text("25%").font(.footnote)
                            .foregroundColor(Color.black)
                            .background(Color.white)
                    }
                    
                    Spacer()
                }
            }
        }.fixedSize(horizontal: false, vertical: true)
    }
}

有很多 VStack / HStack / Divider / Spacer 可以使用一些 HStack 属性进行优化。下面是完全相同的显示,布局代码少得多,并且去掉了古怪的分隔线元素:

struct TesterView: View {
    var body: some View {

        HStack(alignment: .center, spacing: 10) {  // use alignment and spacing instead of all the VStack formatting
                
            // MARK: Time
            Text("9am")
                .padding(.vertical, 20).padding(.horizontal, 5) // specifically set a padding number instead of relying on default
                .background(Color.blue.opacity(0.2)
                                .cornerRadius(8))
                
            // MARK: Icon
            Image(systemName: "cloud.drizzle.fill")
                .font(.title2)
                        
            // MARK: Summary
            Text("Humid and overcast")
                .fixedSize(horizontal:true, vertical:false)
                .background(Color.white)
            
            // MARK: Line
            // note: Rectangle expands to fill space just like Divider, use .frame() to control its height
            // IMO relying on Divider to interpret its parent container and expand properly seems whacky and non-specific
            Rectangle()
                .fill(Color.black.opacity(0.2))
                .padding(.horizontal, 5)
                .frame(height:1)
                        
            // MARK: Values
            VStack {
                Text(String(22.66)).bold().italic()
                Text("25%").font(.footnote)
                    .foregroundColor(Color.black)
                    .background(Color.white)
            }
        }
        .padding(.horizontal, 20) // added HStack padding to push off screen edges
    }
}