I don't really have any knowledge of drawing in Swift, but I'm looking to create part of my app background that's slightly different to a square. See the image below for what I'm trying to make:
The idea is that this will sit at the top of the screen, and be nothing more than a background. It'll stretch half way down the screen. I'll then add an image over the top etc. I would need the point at the bottom of the square to always sit in the middle of the screen.
Can I make this shape/UIView in Swift by code? And if so, how?
Or, is it better to just create this as an image and do it that way?
SwiftUI comes with quite a number of built-in 2D shapes such as Rectangle, Circle, Ellipse, Capsule, RoundedRectangle etc. If all these are not enough to fulfil your needs, you can also create your own custom shapes by using Path
So, the following code is an example on creating a few star shapes and arranged in a HStack in a SwiftUI view. The parameter innerRatio is to control the sharpness of the star's corners, the lower the value the sharper it is. Please leave us your comments below, if you find any errors or mistakes with this post.
Any iOS app has a many views. Those views needs four values specified in order to be displayed: x, y, width, height. There are three different ways of building these views: Storyboards, Nib files and Programmatically.
There are various ways to add PureLayout to your Swift project. I’m using cocoapods, a dependency manager for Swift and Objective-C projects. It requires a file named Podfile that looks like this: Next run the following command to install dependencies, PureLayout in this case: This command will create a new project file that ends in .xcworkspace.
Can I make this shape/UIView in Swift by code? And if so, how?
Views are always rectangular, but a view's content can be any shape at all and it's background can be transparent, so the visible part of a view can be anything you can draw.
There are a lot of ways to draw something in iOS. It's usually best to start with the highest level tool that'll work for you and move down to a lower level when you need more control. With that in mind, I'd suggest starting by creating a view that draws your pentagon using a UIBezierPath
. The (Swift 5) code for this is very simple:
class PentagonView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
backgroundColor = UIColor.clear
}
override func draw(_ rect: CGRect) {
let size = self.bounds.size
let h = size.height * 0.85 // adjust the multiplier to taste
// calculate the 5 points of the pentagon
let p1 = self.bounds.origin
let p2 = CGPoint(x:p1.x + size.width, y:p1.y)
let p3 = CGPoint(x:p2.x, y:p2.y + h)
let p4 = CGPoint(x:size.width/2, y:size.height)
let p5 = CGPoint(x:p1.x, y:h)
// create the path
let path = UIBezierPath()
path.move(to: p1)
path.addLine(to: p2)
path.addLine(to: p3)
path.addLine(to: p4)
path.addLine(to: p5)
path.close()
// fill the path
UIColor.red.set()
path.fill()
}
}
And now you can use that view anywhere in your UI:
If you want to add a 150x150px PentagonView
to your view controller's main view at coordinates (100, 200), you could put the following in viewDidLoad()
:
let pg = PentagonView(frame:CGRect(x:100, y:200, width:150, height:150))
self.view.addSubview(pg)
Or, you could also add a PentagonView
to some view in your storyboard by dropping in a UIView
of the right size and then changing it's class to PentagonView
.
Or, is it better to just create this as an image and do it that way?
If you've fully described your requirement, then no, I don't think so: the image itself will probably be a lot larger than the code that draws it, and the code that I've given above will work at any size you choose. On the other hand, if you're going to add a lot of complex detail, and if the image only needs to appear at one size, then it might be easier to create it once in a drawing program and store that work as an image. Like I said above, there are a lot of options for drawing in iOS; which you choose should be determined by your needs.
Caleb's answer updated to Swift 5:
class PentagonView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
backgroundColor = .clear
}
override func draw(_ rect: CGRect) {
let size = self.bounds.size
let h = size.height * 0.85 // adjust the multiplier to taste
// calculate the 5 points of the pentagon
let p1 = self.bounds.origin
let p2 = CGPoint(x:p1.x + size.width, y:p1.y)
let p3 = CGPoint(x:p2.x, y:p2.y + h)
let p4 = CGPoint(x:size.width/2, y:size.height)
let p5 = CGPoint(x:p1.x, y:h)
// create the path
let path = UIBezierPath()
path.move(to: p1)
path.addLine(to: p2)
path.addLine(to: p3)
path.addLine(to: p4)
path.addLine(to: p5)
path.close()
// fill the path
UIColor.red.set()
path.fill()
}
}
The best way to tackle this is not by creating a view (UIView
) but a layer (CAShapeLayer
). You can create a CAShapeLayer from a path, thus describing your shape with vectors (as opposed to a bitmap).
There are many tutorials about CAShapeLayer that will show you code for achieving this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With