【问题标题】:ForEach inside ScrollView doesn't take whole widthScrollView 中的 ForEach 不占用整个宽度
【发布时间】:2019-06-10 23:49:43
【问题描述】:

我正在尝试使用 SwiftUI 重新创建当前应用的 UI。不过,这比我一开始要困难得多。 我想实现背后有一些背景的卡片式细胞。我发现List 至少现在还不支持。 List 非常有限 - 它不允许您删除单元格分隔符。

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

任何想法如何强制VStack 占据 ScrollView 的整个宽度?我尝试在没有VStack 的情况下使用ForeEach,它也有同样的问题。似乎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)
    }
}

【问题讨论】:

  • 您可以在底部和顶部使用 Spacer() 将 VStack 添加到 HStack,它将全屏显示。不知道这是否适用于滚动视图
  • @PrashantTukadiya 如果我添加HStackVStackSpacer 单元格将不会变成全宽。在 Building Custom Views talk 中,Apple 工程师解释了调整大小的工作原理。从我在这里看到的 - ScrollView 没有传递它的大小,而是一些 ScrollViewContent 的大小(它不是实际名称)小于 ScrollView 本身。将 ScrollView 替换为另一个视图可以解决问题,但我失去了滚动功能。

标签: ios swift swiftui


【解决方案1】:

我遇到了同样的问题,到目前为止我发现的唯一方法是修复 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)")
         }
    }
}

【讨论】:

    【解决方案2】:

    这个问题的答案可能只是将你的 scrollView 包装在 GeometryReader

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

    【讨论】:

      猜你喜欢
      • 2018-08-03
      • 1970-01-01
      • 2019-08-06
      • 1970-01-01
      • 2021-01-30
      • 2013-08-28
      • 1970-01-01
      • 2017-09-17
      • 2012-04-15
      相关资源
      最近更新 更多