Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
468 views
in Technique[技术] by (71.8m points)

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

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 always centered. How can I align them top leading? Here is the view that draws the table:

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)

                }
            }
        }
    }
}

And this is 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
    }
}

This is how it looks like in the app. Notice the edges don't fit inside the screen. Even if I try to scroll there, it just bounces back.

Example screenshot

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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))
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...