During development in SwiftUI, it is an often question to arise – how to size each element on the screen?
The Problem
There are basically two choices:
- keep the dimensions of the element within itself
- set the dimensions during initialisation of the element
Here’s an example of how two approaches look like separately:
Hardcoded Size
struct CircleButton : View {
var action : () -> Void
var body : some View {
// size is set according to the hardcoded values
Button(action: self.action) {
Circle()
.background(Color.blue)
}
.frame(width: Constants.width, height: Constants.height)
}
enum Constants {
static let width : CGFloat = 300
static let height : CGFloat = 80
}
}
GeometryReader-based Size
struct CircleButton : View {
var action : () -> Void
var body : some View {
// size is according to the one specified by either .frame modifier of the CircleButton
// instance, or by the View that contains the button
GeometryReader { geometry in
Button(action: self.action) {
Circle()
.background(Color.blue)
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
}
}
But what if sometimes the button is needed according to its default size, and sometimes – according to the .frame modifier from “outside”?
I have discovered a fairly handy practice of keeping the balance between these two worlds.
In order to overcome this problem, we need a `struct` that would have a default value, and also would be available as an argument of the default initializer of the `CircleButton`:
struct CircleButton : View {
var action : () -> Void
@State var size : Size = .template
var body : some View {
// size is set according to the hardcoded values
Button(action: self.action) {
Circle()
.background(Color.blue)
}
.frame(width: self.size.width, height: self.size.height)
}
struct Size {
var width : CGFloat
var height : CGFloat
static var template : Self { Size(width: 300, height: 80) }
}
}
Now we can use either default size of the button:
CircleButton(action: { print("Hello!" })
or size that we need it to occupy:
CircleButton(action: { print("Hello, resized button!", size: .init(width: 180, height: 40)) }
I hope this post helps you to solve your problem thus leading to speedup in your learning curve of the SwiftUI!
See you next week!