How can I draw custom view as shown in image.
I want to draw a small rectangle in main view.
plaese refer any link if you have.
Image
Thank you
It could be as simple as below
import UIKit
class Rectangle:UIView{
override func draw(_ rect: CGRect) {
let path = UIBezierPath(rect: rect)
path.move(to: CGPoint(x:0,y:rect.height))
path.addLine(to: CGPoint(x:rect.width/2,y:rect.height/1.4))
path.addLine(to: CGPoint(x:rect.width,y:rect.height))
UIColor.red.setStroke()
path.stroke()
}
}
let rect=Rectangle(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
Related
I have a code that draws an ellipse, but it's in a separate class that inherits from UIView
class DRAW: UIView {
override func draw(_ rect: CGRect) {
var path = UIBezierPath()
path = UIBezierPath(ovalIn: CGRect(x: 36.62, y: 77.54, width: 303.19, height: 495.93))
UIColor.green.setFill()
path.stroke()
path.fill()
}
}
If I try to add it via addSubview(), then it is not on the screen, and if I give it the dimensions, then a black crawl for the entire display and only in the middle is the ellipse I need.
view.addSubview(DRAW.init(CGRect(x: 36.62, y: 77.54, width: 303.19, height: 495.93)))
How do I display only an ellipse without a black square. I would be grateful for your help
You can just simply set the clear background color of your view
let yourView = DRAW.init(frame: CGRect(x: 36.62, y: 77.54, width: 303.19, height: 495.93))
yourView.backgroundColor = .clear
self.view.addSubview(yourView)
I created a custom UILabel subclass that has a circle in the middle, and the label's text (which is a number) will be on top of the circle.
I initially thought of doing this using layer.cornerRadius, but that will not create a circle when the label's width and height are not equal.
What I mean is, for a label with width 100 and height 50, I still want a circle with radius 50 and centre at (50, 25).
Therefore, I tried to use UIBezierPath to draw the circle. This is what I have tried:
override func draw(_ rect: CGRect) {
super.draw(rect)
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
}
I have put super.draw(rect) because I thought that would draw the label's text, but when I run the app, I only see the circle and not my label text.
I am very confused because why hasn't super.draw(rect) drawn the label's text?
The text is not seen because the "z-index" of UIBezierPaths depends on the order in which they are drawn. In other words, UIBezierPaths are drawn on top of each other.
super.draw(rect) indeed draws the text. But when you put it as the first statement, it will get drawn first, so everything you draw after that, goes on top of the text. To fix this, you should call super.draw(rect) last:
override func draw(_ rect: CGRect) {
if bounds.height > bounds.width {
let y = (bounds.height - bounds.width) / 2
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: y, width: bounds.width, height: bounds.width))
circleColor.setFill()
path.fill()
} else {
let x = (bounds.width - bounds.height) / 2
let path = UIBezierPath(ovalIn: CGRect(x: x, y: 0, width: bounds.height, height: bounds.height))
circleColor.setFill()
path.fill()
}
super.draw(rect) // <------- here!
}
Alternatively, just subclass UIView, draw the circle in draw(_:), and add a UILabel as a subview of that. The advantage if this approach is that it does not depend on the implementation of super.draw(_:), which might change in the future,
This is my first time in which I've encountered problems with drawRect. I have a simple UIView subclass with a path to fill. Everything is fine. The path gets filled properly, but the background remains black no matter what. What should I do? My code is listed below:
var color: UIColor = UIColor.red {didSet{setNeedsDisplay()}}
private var spaceshipBezierPath: UIBezierPath{
let path = UIBezierPath()
let roomFromTop: CGFloat = 10
let roomFromCenter: CGFloat = 7
path.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
path.addLine(to: CGPoint(x: bounds.minX, y: bounds.minY+roomFromTop))
path.addLine(to: CGPoint(x: bounds.midX-roomFromCenter, y: bounds.minY+roomFromTop))
path.addLine(to: CGPoint(x: bounds.midX-roomFromCenter, y: bounds.minY))
path.addLine(to: CGPoint(x: bounds.midX+roomFromCenter, y: bounds.minY))
path.addLine(to: CGPoint(x: bounds.midX+roomFromCenter, y: bounds.minY+roomFromTop))
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY+roomFromTop))
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))
return path
}
override func draw(_ rect: CGRect) {
color.setFill()
spaceshipBezierPath.fill()
}
Here is what the view looks like:
I have a simple UIView subclass ... but the background remains black no matter what
Typically that sort of thing is because you have forgotten to set the UIView subclass's isOpaque to false. It is a good idea to do this in the UIView subclass's initializer in order for it to be early enough.
For example, here I've adapted your code very slightly. This is the complete code I'm using:
class MyView : UIView {
private var spaceshipBezierPath: UIBezierPath{
let path = UIBezierPath()
// ... identical to your code
return path
}
override func draw(_ rect: CGRect) {
UIColor.red.setFill()
spaceshipBezierPath.fill()
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let v = MyView(frame:CGRect(x: 100, y: 100, width: 200, height: 200))
self.view.addSubview(v)
}
}
Notice the black background:
Now I add these lines to MyView:
override init(frame:CGRect) {
super.init(frame:frame)
self.isOpaque = false
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
See the difference that makes?
In my case what I solved was to switch from Background-Color "No Color", to Background-Color "Clear Color"
For future seekers....
I had the same problem but #matt solution didn’t work for me.
In my scenario, I had a UIView (A) behind another UIView (B).
UIView (A) had a background color and UIView (B) was transparent. Worth to note that B was subclassed to create a custom shape using UIBezier by overriding draw method.
Turned out that in this situation a transparent UIView means nothing and I had to set the same background color for B or either remove background color of A.
there was no other way, so don’t waste your time if you have the same scenario!
I am trying to replicate the layer or view in iOS swift(the one saying follow and or the view with the followers)that is in the red box but i dont know really how to approach this.Should I try by making a view to then making it triangular?
-Try the following code
import UIKit
class animationView: UIView {
override func drawRect(rect: CGRect) {
let path = UIBezierPath()
path.moveToPoint(CGPoint(x: 80, y: 50))
path.addLineToPoint(CGPoint(x: 140, y:150))
path.addLineToPoint(CGPoint(x: 10, y:150))
path.closePath()
UIColor.greenColor().setFill()
UIColor.redColor().setStroke()
path.lineWidth = 3
path.fill()
path.stroke()
}
}
You should have a triangle after this. Adjust the point's x and y value to correctly match your requirements.
I wanna draw a sloping oval with UIBezierPath. There is only a method UIBezierPath.init(ovalInRect: rect) to draw a oval without slop.What can I do to draw this? thanks
Here is an example of a rotated oval:
class MyView: UIView {
override func draw(_ rect: CGRect) {
// create oval centered at (0, 0)
let path = UIBezierPath(ovalIn: CGRect(x: -75, y: -50, width: 150, height: 100))
// rotate it 30 degrees
path.apply(CGAffineTransform(rotationAngle: 30 * .pi / 180))
// translate it to where you want it
path.apply(CGAffineTransform(translationX: self.bounds.width / 2, y: self.bounds.height / 2))
// set stroke color
UIColor.blue.setStroke()
// stroke the path
path.stroke()
}
}
let view = MyView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
view.backgroundColor = .white
Here it is running in a Playground: