Given the following code:
import SwiftUI
struct HomeScreenCounterView: View {
private let value: Int
private let title: String
private let emptyDescription: String
init(value: Int, title: String, emptyDescription: String) {
self.value = value
self.title = title
self.emptyDescription = emptyDescription
}
var body: some View {
VStack {
Text("Messages")
.font(.fontTextLBold)
Text("No new messages")
.font(.fontTextSRegular)
}
.padding()
.clipShape(RoundedRectangle(cornerRadius: 16))
}
}
#Preview {
HomeScreenCounterView(value: 0,
title: "Messages",
emptyDescription: "No new messages")
.foregroundStyle(Color.red)
.background(Color.blue)
}
I get the following result:
Notice, how the text color in both labels has been changed to red.
While the background is correctly displayed as blue, it is obviously not clipped, as the clipping operator has been applied earlier, not later.
What would be the best/the most elegant way to have a background color modifier, similarly to how the other SwiftUI components work?
One of the solutions I am thinking of, and it's obviously a working solution, is to add an initializer parameter:
init(value: Int, title: String, emptyDescription: String, backgroundColor: Color) {
And then using that value to set the background color just after padding
:
.padding()
.background(backgroundColor)
.clipShape(RoundedRectangle(cornerRadius: 16))
But is there a better way?
You could consider using a semantic shape style for filling the background inside the view. The obvious choice would be .background
, but you could also use one of the other semantic or hierarachical styles such as .secondary
. The actual color can then be set from a parent view:
// HomeScreenCounterView
VStack {
// ...
}
.padding()
.background(.background, in: .rect(cornerRadius: 16)) // or, say, .secondary
// Parent
HomeScreenCounterView(
// ...
)
.foregroundStyle(.red)
// .foregroundStyle(.red, .blue) // for setting .blue as secondary
.backgroundStyle(.blue)