SwiftUI如何对齐大于屏幕宽度的视图 [英] SwiftUI How to align a view that's larger than screen width

查看:231
本文介绍了SwiftUI如何对齐大于屏幕宽度的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用SwiftUI绘制一个表,该表的行和列太多,无法容纳屏幕的宽度/高度.在这种情况下,我无法将视图对齐为领先,但总是以某种方式居中.我该如何调整他们的领先地位? 这是绘制表格的视图:

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)

                }
            }
        }
    }
}

这是GridStack:

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.

推荐答案

以下是可能方法的演示(以及改进的方向,因为我没有测试所有情况和可能性)

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

注:如果仅选择一个ScrollView轴,它将自动进行内容对齐,否则我现在感到困惑,但是没有配置功能.因此,以下可能被视为临时解决方法.

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.

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

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.

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

这篇关于SwiftUI如何对齐大于屏幕宽度的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆