在 Swift 中的 UIView 上绘制网格

Posted

技术标签:

【中文标题】在 Swift 中的 UIView 上绘制网格【英文标题】:Drawing a grid on a UIView in Swift 【发布时间】:2017-09-24 13:58:36 【问题描述】:

我对 Swift 很陌生。我试图在 Swift 的 UIView 上绘制网格(如图形页面)。代码正在运行,但我没有看到任何行。我看不出我做错了什么。

在 Storyboard 中,我在 ViewController 上添加了一个视图。

在代码中,我创建了一个 GridView.swift 并将其添加到上面的视图中。这是 GridView 类的代码。正在调用函数 draw 并且代码运行时没有任何错误。它只是在做我认为它会做的事情。

它甚至没有画一条线(我删除了 for 循环并尝试画一条线)。这似乎很基本,应该可以工作。

import Foundation
import UIKit

class GridView: UIView 

    fileprivate var gridWidthMultiple: CGFloat
    
        return 10
    
    fileprivate var gridHeightMultiple : CGFloat
    
        return 20
    

    fileprivate var gridWidth: CGFloat
       
        return bounds.width/CGFloat(gridWidthMultiple)
    

    fileprivate var gridHeight: CGFloat
    
        return bounds.height/CGFloat(gridHeightMultiple)
    

    fileprivate var gridCenter: CGPoint 
        return CGPoint(x: bounds.midX, y: bounds.midY)
    

    fileprivate func drawGrid()
    
        let path = UIBezierPath()
        path.lineWidth = 5.0

        for index in 1...Int(gridWidthMultiple) - 1
        
            let start = CGPoint(x: CGFloat(index) * gridWidth, y: 0)
            let end = CGPoint(x: CGFloat(index) * gridWidth, y:bounds.height)
            path.move(to: start)
            path.addLine(to: end)
        
    

    override func draw(_ rect: CGRect)
    
        drawGrid()
    

【问题讨论】:

【参考方案1】:

只需复制并粘贴以下代码即可。我没有检查你绘制正确网格的逻辑我刚刚解决了不绘制问题。如果它绘制了错误的网格,那么我现在将重新检查您的网格逻辑,它只是帮助您使用UIBezierPath

绘制一些东西
class GridView: UIView

    private var path = UIBezierPath()
    fileprivate var gridWidthMultiple: CGFloat
    
        return 10
    
    fileprivate var gridHeightMultiple : CGFloat
    
        return 20
    

    fileprivate var gridWidth: CGFloat
    
        return bounds.width/CGFloat(gridWidthMultiple)
    

    fileprivate var gridHeight: CGFloat
    
        return bounds.height/CGFloat(gridHeightMultiple)
    

    fileprivate var gridCenter: CGPoint 
        return CGPoint(x: bounds.midX, y: bounds.midY)
    

    fileprivate func drawGrid()
    
        path = UIBezierPath()
        path.lineWidth = 5.0

        for index in 1...Int(gridWidthMultiple) - 1
        
            let start = CGPoint(x: CGFloat(index) * gridWidth, y: 0)
            let end = CGPoint(x: CGFloat(index) * gridWidth, y:bounds.height)
            path.move(to: start)
            path.addLine(to: end)
        

        for index in 1...Int(gridHeightMultiple) - 1 
            let start = CGPoint(x: 0, y: CGFloat(index) * gridHeight)
            let end = CGPoint(x: bounds.width, y: CGFloat(index) * gridHeight)
            path.move(to: start)
            path.addLine(to: end)
        

        //Close the path.
        path.close()

    

    override func draw(_ rect: CGRect)
    
        drawGrid()

        // Specify a border (stroke) color.
        UIColor.purple.setStroke()
        path.stroke()
    

【讨论】:

谢谢。我看到我必须关闭路径并实际调用 stroke() 才能绘制。所以我只是“准备”稍后要绘制的对象,而 stroke() 实际绘制它。 你的意思是说你想在有的时候画出来?比如按钮点击、滑动手势或一些特殊事件之后? 我想说为什么我需要在路径对象上调用 stroke() 和 close()。 Stroke 是您在视图上绘制的路径的颜色。而 close 方法用于关闭绘图,以便系统可以从头到尾开始绘图。关闭定义绘图结束。 网格不可见。我在控制器中添加了一个UIView,将类更改为GridView 。但没有显示任何网格。如何在视图中添加网格?【参考方案2】:

如果您想在视图初始化时创建绘制逻辑,但您实际上想稍后绘制线条,即当某些特殊事件发生时。 Bellow 类有两个方法 drawGridWithStoreColorremoveGrid 这将帮助您在需要时绘制网格并在需要时删除网格。

class GridView: UIView

    private var path = UIBezierPath()
    var gridLayer: CAShapeLayer?

    fileprivate var gridWidthMultiple: CGFloat
    
        return 10
    
    fileprivate var gridHeightMultiple : CGFloat
    
        return 20
    

    fileprivate var gridWidth: CGFloat
    
        return bounds.width/CGFloat(gridWidthMultiple)
    

    fileprivate var gridHeight: CGFloat
    
        return bounds.height/CGFloat(gridHeightMultiple)
    

    fileprivate var gridCenter: CGPoint 
        return CGPoint(x: bounds.midX, y: bounds.midY)
    

    fileprivate func drawGrid()
    
        path = UIBezierPath()
        path.lineWidth = 5.0

        for index in 1...Int(gridWidthMultiple) - 1
        
            let start = CGPoint(x: CGFloat(index) * gridWidth, y: 0)
            let end = CGPoint(x: CGFloat(index) * gridWidth, y:bounds.height)
            path.move(to: start)
            path.addLine(to: end)
        


    

    //Call this method with your stroke color when you want to draw this grid
    func drawGridWithColor(borderColor: UIColor) 
        //Close the path.
        path.close()
        if gridLayer == nil 
            gridLayer = CAShapeLayer()
            gridLayer?.lineWidth = 5.0;
            gridLayer?.path = path.cgPath
            gridLayer?.strokeColor = borderColor.cgColor

            self.layer.addSublayer(gridLayer!)
            //Above line will add this grid at the very top of this view.



            // if you want to add this grid below some layer/object you can use method
            //self.layer.insertSublayer(gridLayer, at: 0)
            //Give the index number to this method so that it can place this grid at the index

        else 
            gridLayer?.strokeColor = borderColor.cgColor
        
    

    func removeGrid() 
        guard let gLayer = gridLayer else return
        gLayer.removeFromSuperlayer()
    

    override func draw(_ rect: CGRect)
    
        drawGrid()
    

【讨论】:

【参考方案3】:

这类似于 Instagram 的创建模式 文本对齐网格。在viewDidLoad()中添加以下两个函数...

func addVerticalGrid()
    
    let Path = UIBezierPath()
    Path.move(to: CGPoint(x: view.bounds.midX, y: 0))
    Path.addLine(to: CGPoint(x: view.bounds.midX, y: view.frame.height))
    Path.close()
    
    let shapeLayer1 = CAShapeLayer()
    shapeLayer1.path = Path.cgPath
    shapeLayer1.strokeColor = UIColor.red.cgColor
    view.layer.addSublayer(shapeLayer1)


func addHorizontalGrid()
    
    let Path = UIBezierPath()
    Path.move(to: CGPoint(x: 0, y: view.bounds.midY))
    Path.addLine(to: CGPoint(x: view.frame.width, y: view.bounds.midY))
    Path.close()
    
    let shapeLayer2 = CAShapeLayer()
    shapeLayer2.path = Path.cgPath
    shapeLayer2.strokeColor = UIColor.red.cgColor
    view.layer.addSublayer(shapeLayer2)

【讨论】:

以上是关于在 Swift 中的 UIView 上绘制网格的主要内容,如果未能解决你的问题,请参考以下文章

UIView 绘制函数 Swift 的可变参数

Swift 中的 UIScrollView 内的 UIPanGesture

swift中的图表数据

如何在 Swift 3 中的 UIView 上添加右边框?

是否可以通过扩展中的 Swift 4 KeyPaths 在 UIView 上设置属性?

在 UIScrollView 内的 UIView 上绘制草图