🙆
[SwiftUI]ButtonStyleでisEnabledの取得
前回の記事で、SwiftUIのButtonStyle
を使うことでボタンの見た目を整えることができました。
今回は、ボタンの有効/無効をButtonStyle
でどうにかできないか調べました。
やりたいことと問題点
ButtonStyle
を使い、ボタンの有効/無効の状態によって色を変えます。
しかし、ButtonStyle
の実装を見てみると、isPressed
の状態しかありません。なので、ボタンの有効/無効を自前で用意する必要があります。
public protocol ButtonStyle {
associatedtype Body : View
@ViewBuilder func makeBody(configuration: Self.Configuration) -> Self.Body
typealias Configuration = ButtonStyleConfiguration
}
public struct ButtonStyleConfiguration {
public struct Label : View {
public typealias Body = Never
}
public let label: ButtonStyleConfiguration.Label
public let isPressed: Bool
}
解決策1
こちらの記事にあるように、ButtonStyle
の中でカスタムView
を定義して@Environment
で状態isEnabled
を取得する方法です。
解決策2
解決策1を改善し、以下のようにできました。
import SwiftUI
struct CapsuleButtonStyle: ButtonStyle {
@Environment(\.isEnabled) var isEnabled: Bool
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding()
.background(self.isEnabled ? Color.blue : Color.gray)
.foregroundColor(.white)
.font(.body.bold())
.clipShape(Capsule())
.scaleEffect(configuration.isPressed ? 0.95 : 1)
.animation(.easeOut(duration: 0.2))
}
}
特にカスタムView
を定義しなくても取得できていました。
気になることとして、ButtonStyle
をまとめて適用した時にisEnabled
が正しく取れるかどうかですが、調べた限り問題はありませんでした。
Group {
Button("Rounded 1", action: { }).disabled(!self.enabled)
Button("Rounded 2", action: { })
}.buttonStyle(RoundedButtonStyle(cornerRadius: 8.0))
Rounded 1
をdisabledにしても、Rounded 2
はdisableにはならない
サンプルコード
Discussion