ScrollView内部的ForEach不需要整个宽度

时间:2019-06-10 23:49:43

标签: ios swift swiftui

我正在尝试使用SwiftUI重新创建当前应用程序的UI。但是,这比我最初要困难得多。 我想建立类似卡片的单元格,并在其后面添加一些背景。我发现List至少到目前为止还不支持。 List如此有限-不允许您删除单元格分隔符。

所以我搬到了ForEach内部的ScrollView。我想这不是长表生产中应该使用的东西,但现在应该可以使用。我遇到的问题是ForeEach视图无法使用ScrollView提供的所有宽度。我可以设置.frame(...)修饰符,但这需要硬编码宽度,而我绝对不希望这样做。

有什么主意如何强制VStack占据ScrollView的整个宽度?我尝试在不使用ForeEach的情况下使用VStack,并且存在相同的问题。似乎ScrollView(父视图)“告诉”其子视图(VStack)其帧小于实际的ScrollView的帧。然后,基于该信息,子视图将构建其布局和大小。

这是我当前的结果:

这是代码:

struct LandmarkList : View {
    var body: some View {
        NavigationView {
            ScrollView() {
                VStack {
                    Spacer().frame(height: 160)
                    ForEach(landmarkData) { landmark in
                        LandmarkRow(landmark: landmark).padding([.leading, .trailing], 16)
                    }
                }.scaledToFill()
                .background(Color.pink)
            }
            .background(Color.yellow)
            .edgesIgnoringSafeArea(.all)
            .navigationBarTitle(Text("Landmarks"))

        }
    }
}

struct LandmarkRow : View {
    var landmark: Landmark

    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                Text(landmark.name).font(.title)
                Text("Subtitle")
                    .font(.callout)
                    .color(.gray)
            }
            Spacer()
            Text("5 mi")
                .font(.largeTitle)
            }.frame(height: 80)
            .padding()
            .background(Color.white)
            .cornerRadius(16)
            .clipped()
            .shadow(radius: 2)
    }
}

2 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,到目前为止,我发现的唯一方法是修复ScrollView和内容视图 width ,以便您在内容内添加的每个子视图视图将居中。

我创建了一个简单的包装器,将宽度作为初始参数

struct CenteredList<Data: RandomAccessCollection, Content: View>: View where Data.Element: Identifiable {

    public private(set) var width: Length
    private var data: Data
    private var contentBuilder: (Data.Element.IdentifiedValue) -> Content

    init(
        width: Length = UIScreen.main.bounds.width,
        data: Data,
        @ViewBuilder content: @escaping (Data.Element.IdentifiedValue) -> Content)
    {
        self.width = width
        self.data = data
        self.contentBuilder = content
    }

    var body: some View {
        ScrollView {
            VStack {
                ForEach(data) { item in
                    return self.contentBuilder(item)
                }.frame(width: width)
            }
            .frame(width: width)
        }
        .frame(width: width)
    }
}

默认情况下,它采用屏幕宽度(UIScreen.main.bounds.width)。

它的工作原理类似于List视图:

var body: some View {
    TileList(data: 0...3) { index in
        HStack {
            Text("Hello world")
            Text("#\(index)")
         }
    }
}

答案 1 :(得分:1)

对此的答案可能只是将您的scrollView包裹在$_SESSION ['id']

就像在这里的答案一样-> How do I stretch a View to its parent frame with SwiftUI?