Triangle UIView - Swift
CAShapeLayer it can change the shape of layers.
var mask = CAShapeLayer()
mask.frame = self.layer.bounds
let width = self.layer.frame.size.width
let height = self.layer.frame.size.height
var path = CGPathCreateMutable()
CGPathMoveToPoint(path, nil, 30, 0)
CGPathAddLineToPoint(path, nil, width, 0)
CGPathAddLineToPoint(path, nil, width, height)
CGPathAddLineToPoint(path, nil, 0, height)
CGPathAddLineToPoint(path, nil, 30, 0)
mask.path = path
// CGPathRelease(path); - not needed
self.layer.mask = mask
var shape = CAShapeLayer()
shape.frame = self.bounds
shape.path = path
shape.lineWidth = 3.0
shape.strokeColor = UIColor.whiteColor().CGColor
shape.fillColor = UIColor.clearColor().CGColor
self.layer.insertSublayer(shape, atIndex: 0)
Swift 5:
This code worked for me for different sides. for UIView
using CGMutablePath()
and CAShapeLayer()
*Assuming your view's height and width are same.
*Set your views's background color as clearColor.
A) Right Side
@IBOutlet weak var triangleView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.setRightTriangle()
}
func setRightTriangle(){
let heightWidth = triangleView.frame.size.width //you can use triangleView.frame.size.height
let path = CGMutablePath()
path.move(to: CGPoint(x: heightWidth/2, y: 0))
path.addLine(to: CGPoint(x:heightWidth, y: heightWidth/2))
path.addLine(to: CGPoint(x:heightWidth/2, y:heightWidth))
path.addLine(to: CGPoint(x:heightWidth/2, y:0))
let shape = CAShapeLayer()
shape.path = path
shape.fillColor = UIColor.blue.cgColor
triangleView.layer.insertSublayer(shape, at: 0)
}
B) Left Side
func setLeftTriangle(){
let heightWidth = triangleView.frame.size.width
let path = CGMutablePath()
path.move(to: CGPoint(x: heightWidth/2, y: 0))
path.addLine(to: CGPoint(x:0, y: heightWidth/2))
path.addLine(to: CGPoint(x:heightWidth/2, y:heightWidth))
path.addLine(to: CGPoint(x:heightWidth/2, y:0))
let shape = CAShapeLayer()
shape.path = path
shape.fillColor = UIColor.blue.cgColor
triangleView.layer.insertSublayer(shape, at: 0)
}
C) Up Side
func setUpTriangle(){
let heightWidth = triangleView.frame.size.width
let path = CGMutablePath()
path.move(to: CGPoint(x: 0, y: heightWidth))
path.addLine(to: CGPoint(x:heightWidth/2, y: heightWidth/2))
path.addLine(to: CGPoint(x:heightWidth, y:heightWidth))
path.addLine(to: CGPoint(x:0, y:heightWidth))
let shape = CAShapeLayer()
shape.path = path
shape.fillColor = UIColor.blue.cgColor
triangleView.layer.insertSublayer(shape, at: 0)
}
D) Down Side
func setDownTriangle(){
let heightWidth = triangleView.frame.size.width
let path = CGMutablePath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x:heightWidth/2, y: heightWidth/2))
path.addLine(to: CGPoint(x:heightWidth, y:0))
path.addLine(to: CGPoint(x:0, y:0))
let shape = CAShapeLayer()
shape.path = path
shape.fillColor = UIColor.blue.cgColor
triangleView.layer.insertSublayer(shape, at: 0)
}
*Change X any Y values according to your requirement.
Updated for Swift 3:
class TriangleView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.beginPath()
context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
context.closePath()
context.setFillColor(red: 1.0, green: 0.5, blue: 0.0, alpha: 0.60)
context.fillPath()
}
}
Swift 2:
import UIKit
class TriangleView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func drawRect(rect: CGRect) {
var ctx : CGContextRef = UIGraphicsGetCurrentContext()
CGContextBeginPath(ctx)
CGContextMoveToPoint(ctx, CGRectGetMinX(rect), CGRectGetMaxY(rect))
CGContextAddLineToPoint(ctx, CGRectGetMaxX(rect), CGRectGetMaxY(rect))
CGContextAddLineToPoint(ctx, (CGRectGetMaxX(rect)/2.0), CGRectGetMinY(rect))
CGContextClosePath(ctx)
CGContextSetRGBFillColor(ctx, 1.0, 0.5, 0.0, 0.60);
CGContextFillPath(ctx);
}
}
This will start from MinX, MaxY;
Draw a line from the start to MaxX, MaxY;
Draw a line from MaxX,MaxY to MaxX/2, MinY;
Then close the path to the start location.
The next part sets the color you want to use. In this example 255,127,0, Alpha 0.6 Then will fill the path you just drew above with the set color.
Then in your View Controller
Swift 3:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let triangle = TriangleView(frame: CGRect(x: 10, y: 20, width: 25 , height: 30))
triangle.backgroundColor = .white
view.addSubview(triangle)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Swift 2:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let triangle = TriangleView(frame: CGRectMake(10, 20, 25, 30))
triangle.backgroundColor = .whiteColor()
view.addSubview(triangle)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
However, this is going to cause the same problem as the frame of this view is still going to be a rectangle. UIKit works with rectangles, you would have to use another framework, like Sprite Kit.
I've modified the previous code a bit to add margin and fill color as inspectable and it works well with Swift4:
import UIKit
@IBDesignable
class TriangleView : UIView {
var _color: UIColor! = UIColor.blue
var _margin: CGFloat! = 0
@IBInspectable var margin: Double {
get { return Double(_margin)}
set { _margin = CGFloat(newValue)}
}
@IBInspectable var fillColor: UIColor? {
get { return _color }
set{ _color = newValue }
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.beginPath()
context.move(to: CGPoint(x: rect.minX + _margin, y: rect.maxY - _margin))
context.addLine(to: CGPoint(x: rect.maxX - _margin, y: rect.maxY - _margin))
context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY + _margin))
context.closePath()
context.setFillColor(_color.cgColor)
context.fillPath()
}
}