SwiftUI How to align a view that's larger than screen width

后端 未结 1 1285
悲哀的现实
悲哀的现实 2020-12-06 07:22

I\'m drawing a table using SwiftUI that has too many rows and columns to fit into the screen width / height. In this case, I cannot align the view as leading but is somehow

相关标签:
1条回答
  • 2020-12-06 08:01

    Here is a demo of possible approach (and direction of improvements, because I did not test all cases and possibilities)

    Note: if you select only one ScrollView axis it does content alignment automatically, otherwise it is now I assume confused, but does not have capability to be configured. So below might be considered as temporary workaround.

    The idea is to read grid content offset via GeometryReader recalculation of frame in .global. coordinate space and mitigate it explicitly.

    Also there is a try to invalidate and handle offset depending on device orientation (probably not ideal, but as a first try), because they are different.

    enter image description here enter image description here

    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))
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题