首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在SwiftUI HStack中隐藏剪裁视图

如何在SwiftUI HStack中隐藏剪裁视图
EN

Stack Overflow用户
提问于 2020-12-15 15:27:50
回答 3查看 1.8K关注 0票数 5

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

示例布局

代码语言:javascript
运行
复制
 ----------------------------------------- 
|                                         |
|  -------     -------     -------     -------     -------
| | VIEW1 |   | VIEW2 |   | VIEW3 |   | VIEW4 |   | VIEW5 |
|  -------     -------     -------     -------     -------
|                                         |
 -----------------------------------------

在本例中,应该隐藏VIEW5,因为它完全超出了父视图的范围。这可以用.clipped()来完成。

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

SwiftUI布局

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

Solution

  • ❌The
  • 由于itemView的宽度比外部VStack大得多,前缘没有对齐=>☑️最后的视图可能是可见的,即使它不是完全在屏幕上。应该避免这种情况。

代码语言:javascript
运行
复制
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

EN

回答 3

Stack Overflow用户

发布于 2020-12-15 15:30:45

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

代码语言:javascript
运行
复制
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()
}
票数 3
EN

Stack Overflow用户

发布于 2020-12-16 18:05:24

以下是基于您的评论的解决方案。VStack与前导对齐,然后我添加了一个ScrollView来保存项的HStack。此外,我在每个项目中添加了一个白色.overlay,当项目完全移动到屏幕上时,透明度将从1.0 (完全覆盖项)更改为0.0 (显示项)。

还请注意,我将前面的填充移到了VStack中,这样当您向左滚动时,项目就会移动到屏幕的边缘,而不是在填充的地方被切断。

代码语言:javascript
运行
复制
struct DemoView: View {
    let items: [String]
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Demo View:")
                .padding(.leading)

            ScrollView(.horizontal, showsIndicators: false) {
                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)
                            .overlay(
                                GeometryReader { geometry in
                                    Color.white
                                        .opacity(
                                            geometry.frame(in: .global).maxX < UIScreen.main.bounds.width ? 0.0 : 1.0
                                        )
                                }
                            )
                    }
                }
                .background(Color.orange) // Starting HStack
                .padding(.leading)
                .background(Color.green) // Scrollable area
            }
        }
    }
    
}

struct DemoView_Previews: PreviewProvider {
    static var previews: some View {
        DemoView(items: [
            "ONE",
            "TWO",
            "THREE",
            "FOUR",
            "FIVE",
            "SIX",
            "SEVEN",
            "EIGHT",
            "NINE",
            "TEN",
        ])
    }
}
票数 1
EN

Stack Overflow用户

发布于 2020-12-17 07:32:09

这是nicksamo提供的通用内容ViewBuilder的答案。谢谢你的解决方案!:)

代码语言:javascript
运行
复制
import SwiftUI

struct NonClippingView<Item: Hashable, Content: View>: View {
    let items: [Item]
    let isScrollingDisabled: Bool
    let backgroundColor: Color
    let content: (Item) -> Content

    init(items: [Item], isScrollingDisabled: Bool = false, backgroundColor: Color = .white, @ViewBuilder content: @escaping (Item) -> Content) {
        self.items = items
        self.isScrollingDisabled = isScrollingDisabled
        self.backgroundColor = backgroundColor
        self.content = content
    }
    
    var body: some View {
        GeometryReader { proxy in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack {
                    ForEach(items, id: \.self) { item in
                        content(item)
                            .overlay(
                                GeometryReader { geometry in
                                    backgroundColor
                                        .opacity(
                                            geometry.frame(in: .global).maxX < proxy.size.width ? 0.0 : 1.0
                                        )
                                }
                            )
                    }
                }
//                .background(Color.orange) // Starting HStack
                .padding(.leading)
//                .background(Color.green) // Scrollable area
            }
            .disabled(isScrollingDisabled)
        }
    }
    
}

struct NonClippingView_Previews: PreviewProvider {
    static var previews: some View {
        NonClippingView(items: [
            "ONE",
            "TWO",
            "THREE",
            "FOUR",
            "FIVE",
            "SIX",
            "SEVEN",
            "EIGHT",
            "NINE",
            "TEN",
        ], content: { item in
            VStack {
                Image(systemName: "tag")
                Text(item)
                    .lineLimit(1)
                    .fixedSize()
            }
            .padding(.all, 5)
            .font(.body)
            .background(Color.blue)
            .foregroundColor(Color.white)
            .cornerRadius(5)
        })
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65308828

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档