No meu aplicativo, tenho uma variedade de botões. Eles compartilham muitas qualidades, mas variam em cor. Estou tentando escrever uma classe que englobe cada um dos ButtonStyles, deixando claro que a única coisa que varia são suas cores.
O problema é que eu também gostaria de poder usar .tint para um deles. Mas isso é um ShapeStyle
em vez de uma Cor.
struct CommonButtonStyle: ButtonStyle {
@Environment(\.isEnabled) var isEnabled: Bool
@Environment(\.isFocused) var isFocused: Bool
var labelColor: Color
var enabledColor: some ShapeStyle
var pressedColor: Color
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.system(size: 14, weight: .bold))
.padding(.horizontal, 16)
.padding(.vertical, 10)
.foregroundStyle(labelColor)
.frame(maxHeight: 40)
.background((isEnabled && configuration.isPressed) ? pressedColor : enabledColor)
.clipShape(Capsule())
.containerShape(Capsule())
.opacity(isEnabled ? 1 : 0.5)
.focusable()
}
}
O problema aqui é a incompatibilidade dos tipos de retorno e a declaração de var enabledColor: some ShapeStyle
como o compilador reclama queProperty declares an opaque return type, but has no initializer expression from which to infer an underlying type
Existe uma maneira de fazer com que essa variável armazene a Color
ou a ShapeStyle
para que eu possa fazer
CommonButtonStyle(labelColor: .black, enabledColor: .tint, pressedColor: .white)
e
CommonButtonStyle(labelColor: .black, enabledColor: .blue, pressedColor: .white)
Não é permitido. Porque
.background
tem seu conteúdo comoShapeStyle
ouView
, não ambos. Você pode fazer um pequeno experimento para verificar, algo como:Então, nesse cenário,
.background
não vai funcionar de jeito nenhum. Ele não pode ter dois tipos diferentes como seu conteúdo. Você deve encontrar uma solução para dividi-lo, dois.background
separadamente de alguma forma.Obrigado ao @Mojitaba pela solução .
A partir de agora, você pode fazer uma
if
condição como:Saída:
Usar um operador ternário para alternar o estilo de fundo não funciona, porque os tipos não correspondem.
No entanto, você pode usar apenas
background(alignment:content:)
com um switch if-else. Este modificador recebe um closure, que é umViewBuilder
.Outros pontos:
Para passar o
ShapeStyle
para o seu personalizadoButtonStyle
, o estilo personalizado precisa ser transformado em um genérico.Em vez de aplicar
.clipShape(Capsule())
, você pode usar aCapsule
como a forma a ser preenchida pelo fundo.Seus dois exemplos agora são compilados e funcionam: