Reputation: 571
In SwiftUI we may have many pieces of code like this:
Text("Hello World")
.padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
.background(Color.blue)
.cornerRadius(5)
However, as you or any other very experienced and professional developers may aware, we want to stay DRY and absolutely don't want to re-write the modifiers:
.padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
.background(Color.blue)
.cornerRadius(5)
for every Text(...)
or Button
or any other SwiftUI component.
It would be better to wrap the:
.padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
.background(Color.blue)
.cornerRadius(5)
in some kind of method or reusable component. I know how to do it in UIKit, but the question is how do we do that in SwiftUI's declarative way to build GUIs?
Upvotes: 17
Views: 3903
Reputation: 115
you can also use Group:
GoogleAuthUI()
.padding(.horizontal)
.disabled(isLoading)
.opacity(isLoading ? 0.5 : 1)
AppleAuthUI()
.padding(.horizontal)
.disabled(isLoading)
.opacity(isLoading ? 0.5 : 1)
Group {
GoogleAuthUI()
AppleAuthUI()
}
.padding(.horizontal)
.disabled(isLoading)
.opacity(isLoading ? 0.5 : 1)
Upvotes: 0
Reputation: 257719
Here is how it is usually done with custom ViewModifier
, plus depicts example of how it could be configured via parameters:
struct MyTextModifier: ViewModifier {
let corner: CGFloat
func body(content: Content) -> some View {
content
.padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
.background(Color.blue)
.cornerRadius(corner)
}
}
extension View {
func configured(with radius: CGFloat = 5) -> some View {
self.modifier(MyTextModifier(corner: radius))
}
}
struct MyTextModifier_Previews: PreviewProvider {
static var previews: some View {
Text("Hello World")
.configured()
}
}
Tested with Xcode 11.2, iOS 13.2
Upvotes: 19
Reputation: 1216
I would create every component as a view, instead of an extension. That way you can always preview the component and have a central repository of 'reusable' components:
struct customText : View {
let text: String
var body: some View {
Text(string)
.padding(EdgeInsets(top: 3, leading: 3, bottom: 3, trailing: 3))
.background(Color.blue)
.cornerRadius(5)
}
}
Append a preview to the above and you can always view exactly what your text will look like in the preview canvas, making future edits easier.
And to use:
customText(text: "Hello World")
You can still add modifiers to its use. You can then have a single source of views which can be used throughout your app (different text types, buttons, etc).
Upvotes: 5
Reputation: 14388
The easiest way to group modifiers for reuse is to declare them in an extension on View
:
extension View {
func customStyle() -> some View {
self.padding(3)
.background(Color.blue)
.cornerRadius(5)
}
}
then you can just simply use it like this:
Text("Hello World").customStyle()
This will only work when all of the modifiers can be applied to View. When you want to group modifiers specific to Image
you would have to do it in an extension on Image
etc.
Upvotes: 13