如何创建仅显示线条网格的自定义视图?

Sup*_*tar 1 swiftui

我正在制作一个测试应用程序以查看使用 SwiftUI 的感觉,并且我希望我的测试应用程序有一个自定义视图,它是一个垂直线网格,间距指定为状态变量。

但是,我无法弄清楚如何在似乎没有自定义绘图方法的 UI 系统中执行此操作。

import SwiftUI



struct GridBackgroundView : View {

    @State var horizontalSpacing: CGFloat = 48
    @State var verticalSpacing: CGFloat = 48
    @State var anchor: Anchor<CGPoint>.Source = .center


    var numberOfHorizontalGridLines: UInt {
        return // Something?
    }

    var numberOfVerticalGridLines: UInt {
        return // Something?
    }


    var body: some View {
        Group {
            ForEach(0 ... numberOfHorizontalGridLines) { _ in
                // Something?
            }
            ForEach(0 ... numberOfVerticalGridLines) { _ in
                // Something?
            }
        }
    }
}

#if DEBUG
struct GridView_Previews : PreviewProvider {
    static var previews: some View {
        GridBackgroundView()
    }
}
#endif
Run Code Online (Sandbox Code Playgroud)

我不知道在这些// Something?区域放什么。SwiftUI 中没有内置线视图,我一生都无法找出视图的宽度是多少(可能是因为这不是ViewSwiftUI中的一部分?)

Rab*_*med 10

为了使用 SwiftUI 使用路径绘制路径和形状来绘制网格视图

struct GridView: View {

    let rows: CGFloat
    let cols: CGFloat
    let gridColor: Color

    var body: some View {
    
        GeometryReader { geometry in
        
            let width = geometry.size.width
            let height = geometry.size.height
            let xSpacing = width / cols
            let ySpacing = height / rows
        
            Path { path in
            
                for index in 0...Int(cols) {
                    let vOffset: CGFloat = CGFloat(index) * xSpacing
                    path.move(to: CGPoint(x: vOffset, y: 0))
                    path.addLine(to: CGPoint(x: vOffset, y: height))
                }
                for index in 0...Int(rows) {
                    let hOffset: CGFloat = CGFloat(index) * ySpacing
                    path.move(to: CGPoint(x: 0, y: hOffset))
                    path.addLine(to: CGPoint(x: width, y: hOffset))
                }
            }
            .stroke(gridColor)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
GridView(rows: 9.0, cols: 9.0, gridColor: .white)
Run Code Online (Sandbox Code Playgroud)

输出网格视图


Arg*_*gas 5

您可以通过组合垫片和分隔器来做到这一点

   var body: some View {
           ZStack {
               HStack {
                   Spacer()
                   Rectangle().frame(width: 1)
                   Spacer()
                   Divider()
                   Spacer()
               }
               VStack {
                   Spacer()
                   Divider()
                   Spacer()
                   Divider()
                   Spacer()
               }
           }
       }
Run Code Online (Sandbox Code Playgroud)

您还可以使用 Rectangle() 而不是 Divider() 并查看 https://developer.apple.com/tutorials/swiftui/drawing-paths-and-shapes

更新:如果您需要一个具有固定大小单元格的网格,您可以使用它GeometryReader来计算行数,并ForEach相应地组织您的行数

    var cellSize: CGFloat = 48
    var body: some View {
        GeometryReader { geometry in
            ZStack {
                HStack {
                    ForEach(0..<Int(geometry.size.width / self.cellSize)) { _ in
                        Spacer()
                        Divider()
                    }
                    Spacer().frame(width: geometry.size.width.truncatingRemainder(dividingBy: self.cellSize))
                }
                VStack {
                    ForEach(0..<Int(geometry.size.height / self.cellSize)) { _ in
                        Spacer()
                        Divider()
                    }
                    Spacer().frame(width: geometry.size.height.truncatingRemainder(dividingBy: self.cellSize))
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)


Mar*_*cio 5

您可以SwiftUI使用Path路径文档教程)进行自定义绘图

要绘制网格,您可以使用以下内容:

struct ContentView : View {
    var horizontalSpacing: CGFloat = 48
    var verticalSpacing: CGFloat = 48

    var body: some View {
        GeometryReader { geometry in
            Path { path in
                let numberOfHorizontalGridLines = Int(geometry.size.height / self.verticalSpacing)
                let numberOfVerticalGridLines = Int(geometry.size.width / self.horizontalSpacing)
                for index in 0...numberOfVerticalGridLines {
                    let vOffset: CGFloat = CGFloat(index) * self.horizontalSpacing
                    path.move(to: CGPoint(x: vOffset, y: 0))
                    path.addLine(to: CGPoint(x: vOffset, y: geometry.size.height))
                }
                for index in 0...numberOfHorizontalGridLines {
                    let hOffset: CGFloat = CGFloat(index) * self.verticalSpacing
                    path.move(to: CGPoint(x: 0, y: hOffset))
                    path.addLine(to: CGPoint(x: geometry.size.width, y: hOffset))
                }
            }
            .stroke()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)