If I already have a button whose font size is defined by the .font()
modifier like below:
Button("Hello"){}
.font(.system(size: 10))
How can I use a ButtonStyle
with .buttonStyle()
to decide the size of this button?
struct CustomButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
let size = 2 * configuration.label.fontSize // Something like this
configuration.label
.frame(width: size, height: size)
.background(.red)
}
}
Or is there some alternatives to this approach? I tried using .padding()
directly. But it don't work properly. As you can see in above screenshot, different sizes were generated because the different sizes of SF Symbols.
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding()
.background(.red)
}
CodePudding user response:
SwiftUI allows to create Font but does not allow to read font properties, so you have to store that at some model layer (say as UIFont) and inject it from outside. Or don't use that at all but some dynamic things, like padding, etc., because Text/Label adopts font sizes-to-frames automatically.
Here is what I meant:
private let uiFont = UIFont.preferredFont(forTextStyle: .title1)
private var font: Font { Font(uiFont as CTFont) }
var body: some View {
HStack {
Button(action: {}) {
Image(systemName: "star")
}
Button(action: {}) {
Image(systemName: "bolt.horizontal")
}
}
.buttonStyle(CustomButtonStyle(font: uiFont)) // << !!
.font(font) // << !!
and style
struct CustomButtonStyle: ButtonStyle {
var font = UIFont.preferredFont(forTextStyle: .body) // << default !!
func makeBody(configuration: Configuration) -> some View {
let size = font.lineHeight * 2.0 // << can use any param and/or factor !!
configuration.label
.frame(width: size, height: size)
.background(.red)
}
}
That gives (Xcode 13.4 / iOS 15.5):
CodePudding user response:
The frame of the button will adapt to fit the content of the button, in our case the text with it's font. Try:
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding()
.background(.red)
}
You can leave the .padding()
out, I added it just for visual purpose.