Display only the corners of a UIView - ios

How to display only the corners of a UIView?
let view = UIView()
view.layer.borderColor = UIColor.white.cgColor
view.layer.borderWidth = 2
let maskframe = UIView(frame: CGRect(x:0, y:0,
width:view.frame.width, height:view.frame.height))
view.layer.mask = maskframe.layer.`
This masks only the right edge and i dont understand how it works either.

Try with this class, here I use a custom view drawing using CoreGraphics, added some Inspectable variables to help with customization
//
// CornerView.swift
// CornersViewSO
//
// Created by Reinier Melian on 5/31/17.
// Copyright © 2017 Reinier Melian. All rights reserved.
//
import UIKit
import CoreGraphics
#IBDesignable
class CornerView: UIView {
#IBInspectable
var sizeMultiplier : CGFloat = 0.2{
didSet{
self.draw(self.bounds)
}
}
#IBInspectable
var lineWidth : CGFloat = 2{
didSet{
self.draw(self.bounds)
}
}
#IBInspectable
var lineColor : UIColor = UIColor.black{
didSet{
self.draw(self.bounds)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.backgroundColor = UIColor.clear
}
func drawCorners()
{
let currentContext = UIGraphicsGetCurrentContext()
currentContext?.setLineWidth(lineWidth)
currentContext?.setStrokeColor(lineColor.cgColor)
//first part of top left corner
currentContext?.beginPath()
currentContext?.move(to: CGPoint(x: 0, y: 0))
currentContext?.addLine(to: CGPoint(x: self.bounds.size.width*sizeMultiplier, y: 0))
currentContext?.strokePath()
//top rigth corner
currentContext?.beginPath()
currentContext?.move(to: CGPoint(x: self.bounds.size.width - self.bounds.size.width*sizeMultiplier, y: 0))
currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: 0))
currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height*sizeMultiplier))
currentContext?.strokePath()
//bottom rigth corner
currentContext?.beginPath()
currentContext?.move(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height - self.bounds.size.height*sizeMultiplier))
currentContext?.addLine(to: CGPoint(x: self.bounds.size.width, y: self.bounds.size.height))
currentContext?.addLine(to: CGPoint(x: self.bounds.size.width - self.bounds.size.width*sizeMultiplier, y: self.bounds.size.height))
currentContext?.strokePath()
//bottom left corner
currentContext?.beginPath()
currentContext?.move(to: CGPoint(x: self.bounds.size.width*sizeMultiplier, y: self.bounds.size.height))
currentContext?.addLine(to: CGPoint(x: 0, y: self.bounds.size.height))
currentContext?.addLine(to: CGPoint(x: 0, y: self.bounds.size.height - self.bounds.size.height*sizeMultiplier))
currentContext?.strokePath()
//second part of top left corner
currentContext?.beginPath()
currentContext?.move(to: CGPoint(x: 0, y: self.bounds.size.height*sizeMultiplier))
currentContext?.addLine(to: CGPoint(x: 0, y: 0))
currentContext?.strokePath()
}
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
super.draw(rect)
self.drawCorners()
}
}
EDITED
Example Code of Use
import UIKit
class ViewController: UIViewController {
var cornerViewCode : CornerView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.cornerViewCode = CornerView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
self.view.addSubview(self.cornerViewCode!)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
this is how it looks
Hope this helps

Check out this UIView:
class RectangleView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
let aPath = UIBezierPath()
UIColor.black.set()
aPath.move(to: CGPoint(x: rect.minX, y: 0.1*rect.maxY))
aPath.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
aPath.addLine(to: CGPoint(x: 20, y: rect.minY))
aPath.stroke()
aPath.move(to: CGPoint(x: rect.maxX - 0.1*rect.maxX, y: rect.minY))
aPath.addLine(to: CGPoint(x: rect.maxX, y: rect.minY))
aPath.addLine(to: CGPoint(x: rect.maxX, y: 0.1*rect.maxY))
aPath.stroke()
aPath.move(to: CGPoint(x: rect.maxX, y: rect.maxY - 0.1*rect.maxY))
aPath.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
aPath.addLine(to: CGPoint(x: rect.maxX - 0.1*rect.maxX, y: rect.maxY))
aPath.stroke()
aPath.move(to: CGPoint(x: rect.minX + 0.1*rect.maxX, y: rect.maxY))
aPath.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
aPath.addLine(to: CGPoint(x: rect.minX, y: rect.maxY - 0.1*rect.maxY))
aPath.stroke()
}
}

If you don't wish to subclass UIView. The same can be achieved using Autolayout.
Swift Version: 3.0
Xcode Version 8.2.1
func setupAutoLayout() {
let cameraViewWidth : Float = Float(UIScreen.main.bounds.size.width * 0.50)
let edgeLength : Float = cameraViewWidth * 0.10
cameraView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
cameraView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
cameraView.widthAnchor.constraint(equalToConstant: CGFloat(cameraViewWidth)).isActive = true
cameraView.heightAnchor.constraint(equalToConstant: CGFloat(cameraViewWidth)).isActive = true
//Top Left
topLeftEdgeView.leadingAnchor.constraint(equalTo: cameraView.leadingAnchor).isActive = true
topLeftEdgeView.topAnchor.constraint(equalTo: cameraView.topAnchor).isActive = true
topLeftEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
topLeftEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
topLeftSideEdgeView.leadingAnchor.constraint(equalTo: cameraView.leadingAnchor).isActive = true
topLeftSideEdgeView.topAnchor.constraint(equalTo: cameraView.topAnchor).isActive = true
topLeftSideEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
topLeftSideEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
//Top Right
topRightEdgeView.trailingAnchor.constraint(equalTo: cameraView.trailingAnchor).isActive = true
topRightEdgeView.topAnchor.constraint(equalTo: cameraView.topAnchor).isActive = true
topRightEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
topRightEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
topRightSideEdgeView.trailingAnchor.constraint(equalTo: cameraView.trailingAnchor).isActive = true
topRightSideEdgeView.topAnchor.constraint(equalTo: cameraView.topAnchor).isActive = true
topRightSideEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
topRightSideEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
//Bottom Left
bottomLeftEdgeView.leadingAnchor.constraint(equalTo: cameraView.leadingAnchor).isActive = true
bottomLeftEdgeView.bottomAnchor.constraint(equalTo: cameraView.bottomAnchor, constant : -CGFloat(1.0)).isActive = true
bottomLeftEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
bottomLeftEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
bottomLeftSideEdgeView.leadingAnchor.constraint(equalTo: cameraView.leadingAnchor).isActive = true
bottomLeftSideEdgeView.topAnchor.constraint(equalTo: cameraView.bottomAnchor, constant : -CGFloat(edgeLength + 1.0)).isActive = true
bottomLeftSideEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
bottomLeftSideEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
//Bottom Right
bottomRightEdgeView.trailingAnchor.constraint(equalTo: cameraView.trailingAnchor).isActive = true
bottomRightEdgeView.bottomAnchor.constraint(equalTo: cameraView.bottomAnchor, constant : -CGFloat(1.0)).isActive = true
bottomRightEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
bottomRightEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
bottomRightSideEdgeView.trailingAnchor.constraint(equalTo: cameraView.trailingAnchor).isActive = true
bottomRightSideEdgeView.topAnchor.constraint(equalTo: cameraView.bottomAnchor, constant : -CGFloat(edgeLength + 1.0)).isActive = true
bottomRightSideEdgeView.widthAnchor.constraint(equalToConstant: CGFloat(1.0)).isActive = true
bottomRightSideEdgeView.heightAnchor.constraint(equalToConstant: CGFloat(edgeLength)).isActive = true
}
PS: Where cameraView, topLeftEdgeView, topLeftSideEdgeView... etc all are UIViews.
Here our edgeLength is dependent on cameraView width(currently 10%).
At 0.50 this will draw complete border around cameraView.
Don't Forget to add translatesAutoresizingMaskIntoConstraints = false for all views involved!!

I was able to achieve the same via BeizerPath and CAShapeLayer. Hence sharing the same.
Code created on Xcode 9.3 using Swift 4.0. Tested on iOS 10.0 and iOS 11.3
func createCorners() -> Void {
//Calculate the length of corner to be shown
let cornerLengthToShow = self.bounds.size.height * 0.10
print(cornerLengthToShow)
// Create Paths Using BeizerPath for all four corners
let topLeftCorner = UIBezierPath()
topLeftCorner.move(to: CGPoint(x: self.bounds.minX, y: self.bounds.minY + cornerLengthToShow))
topLeftCorner.addLine(to: CGPoint(x: self.bounds.minX, y: self.bounds.minY))
topLeftCorner.addLine(to: CGPoint(x: self.bounds.minX + cornerLengthToShow, y: self.bounds.minY))
let topRightCorner = UIBezierPath()
topRightCorner.move(to: CGPoint(x: self.bounds.maxX - cornerLengthToShow, y: self.bounds.minY))
topRightCorner.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.minY))
topRightCorner.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.minY + cornerLengthToShow))
let bottomRightCorner = UIBezierPath()
bottomRightCorner.move(to: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY - cornerLengthToShow))
bottomRightCorner.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.maxY))
bottomRightCorner.addLine(to: CGPoint(x: self.bounds.maxX - cornerLengthToShow, y: self.bounds.maxY ))
let bottomLeftCorner = UIBezierPath()
bottomLeftCorner.move(to: CGPoint(x: self.bounds.minX, y: self.bounds.maxY - cornerLengthToShow))
bottomLeftCorner.addLine(to: CGPoint(x: self.bounds.minX, y: self.bounds.maxY))
bottomLeftCorner.addLine(to: CGPoint(x: self.bounds.minX + cornerLengthToShow, y: self.bounds.maxY))
let combinedPath = CGMutablePath()
combinedPath.addPath(topLeftCorner.cgPath)
combinedPath.addPath(topRightCorner.cgPath)
combinedPath.addPath(bottomRightCorner.cgPath)
combinedPath.addPath(bottomLeftCorner.cgPath)
let shapeLayer = CAShapeLayer()
shapeLayer.path = combinedPath
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 3
layer.addSublayer(shapeLayer)
}

Related

How to use lineJoin and lineJoinStyle with a UIBezierPath?

I have a mask applied to a view using CAShapeLayer and UIBezierPath. I'd like to add a rounding effect to the line joins but it's not working. How do I round the corners of this shape?
You can plug the following into an Xcode playground.
import PlaygroundSupport
import UIKit
private class ProfileImageView: UIView {
private let imageView = UIImageView()
var image: UIImage?
override init(frame: CGRect) {
super.init(frame: frame)
imageView.clipsToBounds = true
imageView.backgroundColor = UIColor.black
imageView.contentMode = .scaleAspectFill
imageView.translatesAutoresizingMaskIntoConstraints = false
addSubview(imageView)
imageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
imageView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
imageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
return nil
}
override func draw(_ rect: CGRect) {
let h = rect.height
let w = rect.width
let path = UIBezierPath()
let shapeLayer = CAShapeLayer()
path.move(to: .zero)
path.addLine(to: CGPoint(x: w-32, y: 0))
path.addLine(to: CGPoint(x: w, y: 32))
path.addLine(to: CGPoint(x: w, y: h))
path.addLine(to: CGPoint(x: 32, y: h))
path.addLine(to: CGPoint(x: 0, y: h-32))
path.close()
path.lineJoinStyle = .round
shapeLayer.lineJoin = .round
shapeLayer.path = path.cgPath
layer.mask = shapeLayer
imageView.image = image
}
}
class VC: UIViewController {
override func loadView() {
view = UIView()
view.backgroundColor = .gray
let imgView = ProfileImageView()
imgView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(imgView)
imgView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
imgView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
imgView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -64).isActive = true
imgView.heightAnchor.constraint(equalTo: view.widthAnchor, constant: -64).isActive = true
}
}
PlaygroundPage.current.liveView = VC()
lineJoinStyle is only for stroked paths. Since yours is a mask, you need a filled path instead so I think you'll need to use path.addCurve to achieve rounded corners in your mask. Or depending on your shape and size you may be able to just apply lineWidth, strokeColor and lineJoinStyle to your CAShapeLayer and get the rounded effect you're looking for.
Still trying to guess at your goal, but maybe this is what you're looking for?
private class ProfileImageView: UIImageView {
public var cornerRadius: Double = 16 {
didSet {
setNeedsLayout()
}
}
public var angleRadius: Double = 24 {
didSet {
setNeedsLayout()
}
}
public var angleIndent: CGFloat = 32 {
didSet {
setNeedsLayout()
}
}
private let shapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
contentMode = .scaleAspectFill
layer.mask = shapeLayer
}
override func layoutSubviews() {
super.layoutSubviews()
let rect = bounds
let path = CGMutablePath()
path.move(to: CGPoint(x: rect.minX, y: rect.midY))
path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.minY),
tangent2End: CGPoint(x: rect.maxX, y: rect.minY),
radius: cornerRadius)
path.addArc(tangent1End: CGPoint(x: rect.maxX - angleIndent, y: rect.minY),
tangent2End: CGPoint(x: rect.maxX, y: rect.minY + angleIndent),
radius: angleRadius)
path.addArc(tangent1End: CGPoint(x: rect.maxX, y: rect.minY + angleIndent),
tangent2End: CGPoint(x: rect.maxX, y: rect.maxY),
radius: angleRadius)
path.addArc(tangent1End: CGPoint(x: rect.maxX, y: rect.maxY),
tangent2End: CGPoint(x: rect.minX, y: rect.maxY),
radius: cornerRadius)
path.addArc(tangent1End: CGPoint(x: rect.minX + angleIndent, y: rect.maxY),
tangent2End: CGPoint(x: rect.minX, y: rect.maxY - angleIndent),
radius: angleRadius)
path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.maxY - angleIndent),
tangent2End: CGPoint(x: rect.minX, y: rect.minY),
radius: angleRadius)
path.closeSubpath()
shapeLayer.path = path
}
}
class VC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBlue
guard let img = UIImage(named: "sampleImage") else {
fatalError("Could not load sample image!!")
}
let stackView = UIStackView()
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.spacing = 20
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
let imgView1 = ProfileImageView(frame: .zero)
imgView1.image = img
let imgView2 = ProfileImageView(frame: .zero)
imgView2.image = img
// top view uses default properties,
stackView.addArrangedSubview(imgView1)
// slightly different properties for the bottom view
imgView2.cornerRadius = 24
imgView2.angleRadius = 32
imgView2.angleIndent = 48
stackView.addArrangedSubview(imgView2)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
stackView.centerXAnchor.constraint(equalTo: g.centerXAnchor),
stackView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
stackView.widthAnchor.constraint(equalTo: g.widthAnchor, constant: -100.0),
imgView1.heightAnchor.constraint(equalTo: imgView1.widthAnchor),
])
}
}

Swift Tabbar with a custom shape in the middle

i want to make this shape in swift .
As you can see, the tabbar has a raised center button. However, this is not the only thing as there should be a real hole in the tabbar so that it is transparent there.
How can I create such a hole inside a tabbar? And then put a raised, round button in that hole?
I would gladly appreciate any help regarding my question.
i am trying but cannot achieve the above result.
import Foundation
import UIKit
#IBDesignable
class AppTabBar: UITabBar {
private var shapeLayer: CALayer?
override func draw(_ rect: CGRect) {
self.addShape()
}
private func addShape() {
let shapeLayer = CAShapeLayer()
shapeLayer.path = createPath()
shapeLayer.strokeColor = UIColor.lightGray.cgColor
shapeLayer.fillColor = #colorLiteral(red: 0.9782002568, green: 0.9782230258, blue: 0.9782107472, alpha: 1)
shapeLayer.lineWidth = 0.5
// The below 4 lines are for shadow above the bar. you can skip them if you do not want a shadow
shapeLayer.shadowOffset = CGSize(width:0, height:0)
shapeLayer.shadowRadius = 10
shapeLayer.shadowColor = UIColor.gray.cgColor
shapeLayer.shadowOpacity = 0.3
if let oldShapeLayer = self.shapeLayer {
self.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
} else {
self.layer.insertSublayer(shapeLayer, at: 0)
}
self.shapeLayer = shapeLayer
}
func createPath() -> CGPath {
let height2: CGFloat = self.frame.height
let height: CGFloat = 86.0
let path = UIBezierPath()
let centerWidth = self.frame.width / 2
let startXpoint = centerWidth - height + 57
let endXpoint = (centerWidth + height - 45)
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: startXpoint , y: 0))
// path.addCurve(to: CGPoint(x: centerWidth, y: height - 40),
// controlPoint1: CGPoint(x: (centerWidth - 30), y: 0), controlPoint2: CGPoint(x: centerWidth - 35, y: height - 40))
path.addCurve(to: CGPoint(x: centerWidth, y: height / 1.6),
controlPoint1: CGPoint(x: startXpoint - 5, y: height2 / 3), controlPoint2: CGPoint(x: (centerWidth - 10), y: height2 / 1.6))
path.addCurve(to: CGPoint(x: (centerWidth + height / 2.9 ), y: 0),
controlPoint1: CGPoint(x: centerWidth + 35, y: height - 40), controlPoint2: CGPoint(x: (centerWidth + 30), y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
path.addLine(to: CGPoint(x: 0, y: self.frame.height))
path.close()
return path.cgPath
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard !clipsToBounds && !isHidden && alpha > 0 else { return nil }
for member in subviews.reversed() {
let subPoint = member.convert(point, from: self)
guard let result = member.hitTest(subPoint, with: event) else { continue }
return result
}
return nil
}
}
extension UITabBar {
override open func sizeThatFits(_ size: CGSize) -> CGSize {
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 74
return sizeThatFits
}
}

CustomView with squiggle(wavy) top.(Swift)

I am trying to create a custom view a squiggle top and add an image view in the middle.
Something like this:
But I am not so used to UIBezierPath, so I am pretty confused.
This is what I have done so far.
class DemoView: UIView {
var path: UIBezierPath!
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.darkGray
complexShape()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
complexShape()
}
func complexShape() {
path = UIBezierPath()
path.move(to: CGPoint(x: 0.0, y: 0.0))
path.addLine(to: CGPoint(x: self.frame.size.width/2 - 50.0, y: 0.0))
path.addLine(to: CGPoint(x: self.frame.size.width/2, y: 0.0))
path.addCurve(to: CGPoint(x: self.frame.size.width, y: 50.0),
controlPoint1: CGPoint(x: self.frame.size.width + 50.0, y: 25.0),
controlPoint2: CGPoint(x: self.frame.size.width - 150.0, y: 50.0))
path.addLine(to: CGPoint(x: self.frame.size.width, y: self.frame.size.height))
path.addLine(to: CGPoint(x: 0.0, y: self.frame.size.height))
path.close()
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
self.layer.mask = shapeLayer
}
}
extension CGFloat {
func toRadians() -> CGFloat {
return self * .pi / 180.0
}
}
The method below will let you add the background wave effect to another view. All you then need to do for the foreground square is add another view. Play with the constants to change the wave shape/height.
func addWaveBackground(to view: UIView){
let leftDrop:CGFloat = 0.4
let rightDrop: CGFloat = 0.3
let leftInflexionX: CGFloat = 0.4
let leftInflexionY: CGFloat = 0.47
let rightInflexionX: CGFloat = 0.6
let rightInflexionY: CGFloat = 0.22
let backView = UIView(frame: view.frame)
backView.backgroundColor = .gray
view.addSubview(backView)
let backLayer = CAShapeLayer()
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x:0, y: view.frame.height * leftDrop))
path.addCurve(to: CGPoint(x:view.frame.width, y: view.frame.height * rightDrop),
controlPoint1: CGPoint(x: view.frame.width * leftInflexionX, y: view.frame.height * leftInflexionY),
controlPoint2: CGPoint(x: view.frame.width * rightInflexionX, y: view.frame.height * rightInflexionY))
path.addLine(to: CGPoint(x:view.frame.width, y: 0))
path.close()
backLayer.fillColor = UIColor.blue.cgColor
backLayer.path = path.cgPath
backView.layer.addSublayer(backLayer)
}
Pass in the view you want to add the wave effect to (this will usually be the VC's main view).

How to clip a UIView with a bezier path?

I'm not totally sure to understand how UIBezierPath is supposed to work.
I have added a simple UIView in the middle of the screen, and I wanted to clip it by adding a mask to its layer. I tried this, thinking I'd get something like a losange in the middle of the view:
override func viewDidLoad() {
super.viewDidLoad()
viewToClip.backgroundColor = .white
let bezierPath = UIBezierPath()
bezierPath.move(to: viewToClip.center)
bezierPath.addLine(to: CGPoint(x: viewToClip.center.x - 5, y: viewToClip.center.y))
bezierPath.addLine(to: CGPoint(x: viewToClip.center.x, y: viewToClip.center.y - 5))
bezierPath.addLine(to: CGPoint(x: viewToClip.center.x + 5, y: viewToClip.center.y))
bezierPath.addLine(to: CGPoint(x: viewToClip.center.x, y: viewToClip.center.y + 5))
bezierPath.close()
let testLayer = CAShapeLayer()
testLayer.path = bezierPath.cgPath
viewToClip.layer.mask = testLayer
}
But instead of that, the view simply disappears from the screen. What am I doing wrong?
Thanks for your help.
Can you try
import UIKit
class bb: UIView {
var once:Bool = true
override func draw(_ rect: CGRect) {
if(once)
{
once = false
self.backgroundColor = .white
let bezierPath = UIBezierPath()
let cen = CGPoint.init(x: self.bounds.size.width/2, y: self.bounds.size.height/2)
bezierPath.move(to: cen)
bezierPath.addLine(to: CGPoint(x: cen.x - 5, y: cen.y))
bezierPath.addLine(to: CGPoint(x: cen.x, y: cen.y - 5))
bezierPath.addLine(to: CGPoint(x: cen.x + 5, y: cen.y))
bezierPath.addLine(to: CGPoint(x: cen.x, y: cen.y + 5))
bezierPath.close()
let testLayer = CAShapeLayer()
testLayer.path = bezierPath.cgPath
testLayer.lineWidth = 1.0
testLayer.strokeColor = UIColor.blue.cgColor
testLayer.fillColor = UIColor.green.cgColor
self.layer.addSublayer(testLayer)
}
}

How to control an UIView's rounded corners separately using #IBInspectable in Swift 3?

Here is my current code:
override func viewDidLoad() {
super.viewDidLoad()
let rect = Draw(frame: CGRect(
origin: CGPoint(x: 50, y: 50),
size: CGSize(width: 100, height: 100)))
self.view.addSubview(rect)
}
Use this custom class, basically you need create a bezier path, using lines and quad curves, handling every corner with values in #IBInspectable properties.
This is the code
//
// CornerView.swift
// UIViewCornerRounded
//
// Created by Reinier Melian on 21/07/2017.
// Copyright © 2017 Pruebas. All rights reserved.
//
import UIKit
#IBDesignable
class CornerView: UIView {
#IBInspectable var leftTopRadius : CGFloat = 0{
didSet{
self.applyMask()
}
}
#IBInspectable var rightTopRadius : CGFloat = 0{
didSet{
self.applyMask()
}
}
#IBInspectable var rightBottomRadius : CGFloat = 0{
didSet{
self.applyMask()
}
}
#IBInspectable var leftBottomRadius : CGFloat = 0{
didSet{
self.applyMask()
}
}
override func layoutSubviews() {
super.layoutSubviews()
self.applyMask()
}
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
/*override func draw(_ rect: CGRect) {
super.draw(rect)
}*/
func applyMask()
{
let shapeLayer = CAShapeLayer(layer: self.layer)
shapeLayer.path = self.pathForCornersRounded(rect:self.bounds).cgPath
shapeLayer.frame = self.bounds
shapeLayer.masksToBounds = true
self.layer.mask = shapeLayer
}
func pathForCornersRounded(rect:CGRect) ->UIBezierPath
{
let path = UIBezierPath()
path.move(to: CGPoint(x: 0 + leftTopRadius , y: 0))
path.addLine(to: CGPoint(x: rect.size.width - rightTopRadius , y: 0))
path.addQuadCurve(to: CGPoint(x: rect.size.width , y: rightTopRadius), controlPoint: CGPoint(x: rect.size.width, y: 0))
path.addLine(to: CGPoint(x: rect.size.width , y: rect.size.height - rightBottomRadius))
path.addQuadCurve(to: CGPoint(x: rect.size.width - rightBottomRadius , y: rect.size.height), controlPoint: CGPoint(x: rect.size.width, y: rect.size.height))
path.addLine(to: CGPoint(x: leftBottomRadius , y: rect.size.height))
path.addQuadCurve(to: CGPoint(x: 0 , y: rect.size.height - leftBottomRadius), controlPoint: CGPoint(x: 0, y: rect.size.height))
path.addLine(to: CGPoint(x: 0 , y: leftTopRadius))
path.addQuadCurve(to: CGPoint(x: 0 + leftTopRadius , y: 0), controlPoint: CGPoint(x: 0, y: 0))
path.close()
return path
}
}
Here is the results
Using this values
Hope this helps
Try this code. In my project it works fine.
extension UIView {
#IBInspectable var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
}

Resources