【问题标题】:SwiftUI How to align a view that's larger than screen widthSwiftUI如何对齐大于屏幕宽度的视图
【发布时间】:2020-01-14 16:10:56
【问题描述】:

我正在使用 SwiftUI 绘制一个表格,该表格的行和列太多,无法适应屏幕的宽度/高度。在这种情况下,我无法将视图对齐为领先,但总是居中。我怎样才能将它们排在首位? 这是绘制表格的视图:

struct TableView: View {
    let columnCount: Int = 9
    let rowCount: Int = 14

    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            ScrollView([.vertical, .horizontal], showsIndicators: false) {
                GridStack(rows: self.rowCount, columns: self.columnCount) { row, col in
                    Text("ROW \(String(row)) COL \(String(col))")
                        .frame(width: 120)

                }
            }
        }
    }
}

这是 GridStack:

struct GridStack<Content: View>: View {
    let rows: Int
    let columns: Int
    let content: (Int, Int) -> Content

    var body: some View {
        VStack(alignment: .leading) {
            ForEach(0 ..< rows) { row in
                HStack(alignment: .top) {
                    ForEach(0 ..< self.columns) { column in
                        self.content(row, column)
                    }
                }
            }
        }
        .padding([.top, .bottom], 20)
    }

    init(rows: Int, columns: Int, @ViewBuilder content: @escaping (Int, Int) -> Content) {
        self.rows = rows
        self.columns = columns
        self.content = content
    }
}

这就是它在应用程序中的样子。注意边缘不适合屏幕。即使我尝试在那里滚动,它也会弹回来。

【问题讨论】:

    标签: ios swift view swiftui


    【解决方案1】:

    这是一个可能的方法的演示(以及改进的方向,因为我没有测试所有的案例和可能性)

    注意:如果您只选择一个ScrollView 轴,它会自动进行内容对齐,否则现在我认为它很混乱,但没有配置能力。因此,以下可能被视为临时解决方法。

    这个想法是通过GeometryReader 重新计算.global. 坐标空间中的帧来读取网格内容偏移量并显式地减轻它。

    还有一个尝试根据设备方向使偏移无效和处理(可能不理想,但作为第一次尝试),因为它们是不同的。

    import Combine
    
    struct TableView: View {
        let columnCount: Int = 9
        let rowCount: Int = 14
    
        @State private var offset: CGFloat = .zero
    
        private let orientationPublisher = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
    
        var body: some View {
            VStack(alignment: .leading, spacing: 20) {
                ScrollView([.horizontal, .vertical], showsIndicators: false) {
                    GridStack(rows: self.rowCount, columns: self.columnCount) { row, col in
                        Text("ROW \(String(row)) COL \(String(col))")
                            .fixedSize()
                            .frame(width: 150)
                    }
                    .background(rectReader())
                    .offset(x: offset)
                }
            }
            .onReceive(orientationPublisher) { _ in
                self.offset = .zero
            }
        }
    
        func rectReader() -> some View {
            return GeometryReader { (geometry) -> AnyView in
                let offset = -geometry.frame(in: .global).minX
                if self.offset == .zero {
                    DispatchQueue.main.async {
                        self.offset = offset
                    }
                }
                return AnyView(Rectangle().fill(Color.clear))
            }
        }
    }
    

    【讨论】:

    • 这很好,解决了问题,谢谢!另外,我将您的 offset 重命名为 offsetX 并创建了一个 offsetY。所以我也可以为 y 轴分配一个偏移量,以防行和列都太大而无法进入视图。
    • 此解决方案不起作用。更新的偏移变量永远不会在 .offset(x:offset) 中设置。它是一个状态变量,所以理论上它应该可以工作,但它不起作用。
    【解决方案2】:

    经过几天的尝试,终于找到了一个最简单的解决方法。希望这能有所帮助。

    func body(content: Content) -> some View {
        GeometryReader { geo in
            ScrollView([.horizontal, .vertical], showsIndicators: true) {
                VStack {
                    ForEach(Range(1...10)) { x in
                        HStack {
                            ForEach(Range(1...10)) { y in
                                Text("\(x), \(y)")
                                    .frame(width: 50, height: 20)
                            }
                            Spacer() // ? 1
                        }
                    }
                    Spacer() // ? 2
                }.frame(minWidth: geo.size.width, minHeight: geo.size.height)  // ? 3
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-05-18
      • 1970-01-01
      • 1970-01-01
      • 2011-01-24
      • 2012-05-19
      • 2014-05-31
      • 2014-03-30
      • 2020-01-03
      • 2013-01-02
      相关资源
      最近更新 更多