swift_dev25
swift_dev25

Reputation: 35

Swift UITableView zigzag borders

I am trying to achieve this aspect for an UITableView : https://www.dropbox.com/s/bcp86myyjgek1kt/Screenshot%202016-11-04%2014.04.14.png?dl=0 and I am stuck.
I followed Atul Manwar's answer :

    func applyZigZagEffect(givenView: UIView) {
    let width = givenView.frame.size.width
    let height = givenView.frame.size.height

    let givenFrame = givenView.frame
    let zigZagWidth = CGFloat(7)
    let zigZagHeight = CGFloat(5)
    let yInitial = height-zigZagHeight

    var zigZagPath = UIBezierPath()
    zigZagPath.moveToPoint(CGPointMake(0, 0))
    zigZagPath.addLineToPoint(CGPointMake(0, yInitial))

    var slope = -1
    var x = CGFloat(0)
    var i = 0
    while x < width {
        x = zigZagWidth * CGFloat(i)
        let p = zigZagHeight * CGFloat(slope)
        let y = yInitial + p
        let point = CGPointMake(x, y)
        zigZagPath.addLineToPoint(point)
        slope = slope*(-1)
        i++
    }
    zigZagPath.addLineToPoint(CGPointMake(width, 0))

    var shapeLayer = CAShapeLayer()
    shapeLayer.path = zigZagPath.CGPath
    givenView.layer.mask = shapeLayer
}  

The result is not the one I am looking for, because I only obtain the bottom border: Achieved using Atul's answer and I have no clue how to change it for both borders ( bottom and top ).

Tried with images, but is not scaled correctly, and I find this solution better, but I am not able to produce the effect for top border.
Thanks!

Upvotes: 2

Views: 2281

Answers (2)

Reinier Melian
Reinier Melian

Reputation: 20804

I had been working on your question and this are my results, use this code,

enter image description here

func applyZigZagEffect(givenView: UIView) {
    let width = givenView.frame.size.width
    let height = givenView.frame.size.height
    
    let givenFrame = givenView.frame
    let zigZagWidth = CGFloat(7)
    let zigZagHeight = CGFloat(5)
    var yInitial = height-zigZagHeight
    
    var zigZagPath = UIBezierPath(rect: givenFrame)
    zigZagPath.move(to: CGPoint(x:0, y:0))
    zigZagPath.addLine(to: CGPoint(x:0, y:yInitial))
    
    var slope = -1
    var x = CGFloat(0)
    var i = 0
    while x < width {
        x = zigZagWidth * CGFloat(i)
        let p = zigZagHeight * CGFloat(slope)
        let y = yInitial + p
        let point = CGPoint(x: x, y: y)
        zigZagPath.addLine(to: point)
        slope = slope*(-1)
        i += 1
    }
    
    zigZagPath.addLine(to: CGPoint(x:width,y: 0))
    
    yInitial = 0 + zigZagHeight
    x = CGFloat(width)
    i = 0
    while x > 0 {
        x = width - (zigZagWidth * CGFloat(i))
        let p = zigZagHeight * CGFloat(slope)
        let y = yInitial + p
        let point = CGPoint(x: x, y: y)
        zigZagPath.addLine(to: point)
        slope = slope*(-1)
        i += 1
    }
    
    var shapeLayer = CAShapeLayer()
    shapeLayer.path = zigZagPath.cgPath
    givenView.layer.mask = shapeLayer
}

I hope this helps you, this code works and was tested

Edited

With this method you can get curved zigzag instead of lines

class func pathSemiCirclesPathForView(givenView: UIView, circlesRadius:CGFloat = 4, circlesDistance : CGFloat = 3, top:Bool = true, bottom:Bool = true ) ->UIBezierPath
    {
        let width = givenView.frame.size.width
        let height = givenView.frame.size.height
        
        let semiCircleWidth = CGFloat(circlesRadius*2)
        
        let semiCirclesPath = UIBezierPath()
        semiCirclesPath.move(to: CGPoint(x:0, y:0))
        
        if(bottom) {
            var x = CGFloat(0)
            var i = 0
            while x < width {
                x = (semiCircleWidth) * CGFloat(i) + (circlesDistance * CGFloat(i))
                let pivotPoint = CGPoint(x: x + semiCircleWidth/2, y: height)
                semiCirclesPath.addArc(withCenter: pivotPoint, radius: circlesRadius, startAngle: -180 * .pi / 180.0, endAngle: 0 * .pi / 180.0, clockwise: true)
                semiCirclesPath.addLine(to: CGPoint(x: semiCirclesPath.currentPoint.x + circlesDistance, y: height))
                i += 1
            }
        }
        else {
            semiCirclesPath.addLine(to: CGPoint(x: 0, y: height))
            semiCirclesPath.addLine(to: CGPoint(x: width, y: height))
        }
        
        semiCirclesPath.addLine(to: CGPoint(x:width,y: 0))
        
        if(top) {
            var x = CGFloat(width)
            var i = 0
            while x > 0 {
                x = width - (semiCircleWidth) * CGFloat(i) - (circlesDistance * CGFloat(i))
                let pivotPoint = CGPoint(x: x - semiCircleWidth/2, y: 0)
                semiCirclesPath.addArc(withCenter: pivotPoint, radius: circlesRadius, startAngle: 0 * .pi / 180.0, endAngle: -180 * .pi / 180.0, clockwise: true)
                semiCirclesPath.addLine(to: CGPoint(x: semiCirclesPath.currentPoint.x - circlesDistance, y: 0))
                i += 1
            }
        }
        
        semiCirclesPath.close()
        
        return semiCirclesPath
    }

RESULTS

enter image description here

Upvotes: 6

swift_dev25
swift_dev25

Reputation: 35

In case somebody else will need it somewhere, I am posting here the result I was looking for with @Reinier Melian 's help. I will soon post another version, customising only the first and last cell of a UITableView.

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var customView: UIView!

    override func viewDidLoad()
    {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.applyZigZagEffect(givenView: customView)
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func pathZigZagForView(givenView: UIView) ->UIBezierPath
    {
        let width = givenView.frame.size.width
        let height = givenView.frame.size.height

        let givenFrame = givenView.frame
        let zigZagWidth = CGFloat(7)
        let zigZagHeight = CGFloat(5)
        var yInitial = height-zigZagHeight

        let zigZagPath = UIBezierPath(rect: givenFrame.insetBy(dx: 5, dy: 5))
        zigZagPath.move(to: CGPoint(x:0, y:0))
        zigZagPath.addLine(to: CGPoint(x:0, y:yInitial))

        var slope = -1
        var x = CGFloat(0)
        var i = 0
        while x < width
        {
            x = zigZagWidth * CGFloat(i)
            let p = zigZagHeight * CGFloat(slope) - 5
            let y = yInitial + p
            let point = CGPoint(x: x, y: y)
            zigZagPath.addLine(to: point)
            slope = slope*(-1)
            i += 1
        }

        zigZagPath.addLine(to: CGPoint(x:width,y: 0))

        yInitial = 0 + zigZagHeight
        x = CGFloat(width)
        i = 0
        while x > 0
        {
            x = width - (zigZagWidth * CGFloat(i))
            let p = zigZagHeight * CGFloat(slope) + 5
            let y = yInitial + p
            let point = CGPoint(x: x, y: y)
            zigZagPath.addLine(to: point)
            slope = slope*(-1)
            i += 1
        }
        zigZagPath.close()
        return zigZagPath
    }

    func applyZigZagEffect(givenView: UIView)
    {
        let shapeLayer = CAShapeLayer(layer: givenView.layer)
        givenView.backgroundColor = UIColor.clear
        shapeLayer.path = self.pathZigZagForView(givenView: givenView).cgPath
        shapeLayer.frame = givenView.bounds
        shapeLayer.fillColor = UIColor.red.cgColor
        shapeLayer.masksToBounds = true
        shapeLayer.shadowOpacity = 1
        shapeLayer.shadowColor = UIColor.black.cgColor
        shapeLayer.shadowOffset = CGSize(width: 0, height: 0)
        shapeLayer.shadowRadius = 3

        givenView.layer.addSublayer(shapeLayer)
    }

}

Result

Upvotes: 0

Related Questions