首页 > 解决方案 > 如何在 SwiftUI HStack 中隐藏剪辑视图

问题描述

SwiftUI 中是否有可能在一行中只显示尽可能多的(固定大小)视图而不进行裁剪,例如裁剪视图的一部分。

示例布局

 ----------------------------------------- 
|                                         |
|  -------     -------     -------     -------     -------
| | VIEW1 |   | VIEW2 |   | VIEW3 |   | VIEW4 |   | VIEW5 |
|  -------     -------     -------     -------     -------
|                                         |
 -----------------------------------------

在这个例子VIEW5中应该被隐藏,因为它完全超出了父视图的范围。这可以通过.clipped().

VIEW4也应该是完全隐藏的!因为如果它要显示,它必须被切断。所有其他视图应正常呈现。

SwiftUI 布局

此初始尝试存在以下问题:

struct DemoView: View {
    let items: [String]
    @State private var totalHeight = CGFloat.zero
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Demo View:")
            itemView
                .padding()
                .background(Color.green)
        }
    }
    
    private var itemView: some View {
        HStack {
            ForEach(items, id: \.self) { item in
                Text(item)
                    .lineLimit(1)
                    .fixedSize()
                    .padding(.all, 5)
                    .font(.body)
                    .background(Color.blue)
                    .foregroundColor(Color.white)
                    .cornerRadius(5)
            }
        }
        .frame(maxWidth: 350)
    }
}

#if DEBUG
struct DemoView_Previews: PreviewProvider {
    static var items: [String] = (2000..<2020).map(String.init)
//        .map { item in
//            Bool.random() ? item : item + item
//        }
    
    static var previews: some View {
        DemoView(items: items)
//            .previewLayout(.sizeThatFits)
    }
}
#endif

错误的布局示例

标签: iosswiftlayoutswiftuiswiftui-list

解决方案


使用裁剪并在HStack框架上对齐(使用 Xcode 12.1 / iOS 14.1 测试)

private var itemView: some View {
    HStack {
        ForEach(items, id: \.self) { item in
            Text(item)
                .lineLimit(1)
                .fixedSize()
                .padding(.all, 5)
                .font(.body)
                .background(Color.blue)
                .foregroundColor(Color.white)
                .cornerRadius(5)
        }
    }
    .frame(maxWidth: 350, alignment: .leading)
    .clipped()
}

推荐阅读