Button ⟩ custom styles
注意:本例使用兩種不同方法來控制 Button 的外觀。
btn1 使用 view modifier,btn2 使用 custom button style。
用 view modifier 必須自行設定 State 變數 isPressed,然而 custom button style 則由 configuration.isPressed 自動監控,不需另行設定 State 變數。
由於 btn1 是由 State 變數來「切換」isPressed 的狀態,所以只要按一下 btn1,按鈕就會陷下去,而且不會彈回來。btn2 則由 configuration.isPressed 自動監控,所以只有持續按住,才會保持「按下的狀態」。
⬆️ 需要: .neumorphic() (modifier)
struct ContentView: View {
@State private var isPressed: Bool = false
let color = Color(white: 0.9)
var body: some View {
HStack {
VStack(alignment: .trailing, spacing: 40) {
btn1 // ⭐️ 1. use view modifier
btn2 // ⭐️ 2. use custom button style
}
.offset(x: -80)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(color)
}
var btn1: some View {
Button{
self.isPressed.toggle()
} label: {
Label("Hello", systemImage: "person")
// ⭐️ 1. view modifier
.neumorphic(isPressed: $isPressed, color: color)
}
.background(color)
.overlay {
Text("點一下就會下沉")
.foregroundColor(.gray)
.offset(x: 150)
}
}
var btn2: some View {
Button{} label: {
Label("World", systemImage: "globe")
}
// ⭐️ 2. custom button style
.buttonStyle(.neumorphic(color: color)) // 🌀 .neumorphic()
.overlay {
Text("要按住才會下沉")
.foregroundColor(.gray)
.offset(x: 150)
}
}
}
import SwiftUI
public struct NeumorphicButtonStyle: ButtonStyle {
var color: Color
// ⭐ protocol's only requirement
public func makeBody(configuration: Self.Configuration) -> some View {
// ⭐ `configuration` contains:
// - .label : content of the button (View)
// - .isPressed: state of the button (Bool)
let isPressed = configuration.isPressed
let s: CGFloat = isPressed ? 5: 15 // positive shadow offset
let r: CGFloat = isPressed ? 7: 10 // shadow radius
let k: CGFloat = isPressed ? 0.95 : 1 // scale
configuration.label
.foregroundColor(.black)
.padding(20)
.background(
ZStack {
RoundedRectangle(cornerRadius: 10, style: .continuous)
.shadow(color: .white, radius: r, x: -s, y: -s)
.shadow(color: .black, radius: r, x: s, y: s)
.blendMode(.overlay)
RoundedRectangle(cornerRadius: 10, style: .continuous)
.fill(color)
}
)
.scaleEffect(k)
.foregroundColor(.primary)
.animation(.spring())
}
}
// 🌀 .neumorphic(color:)
// ╭───────── ⭐️ important ──────────╮
extension ButtonStyle where Self == NeumorphicButtonStyle {
public static func neumorphic(color: Color) -> some ButtonStyle {
NeumorphicButtonStyle(color: color)
}
}
SwiftUI ⟩ Controls ⟩ Button ⟩
ButtonStyle (protocol) - standard button interaction behavior.
PrimitiveButtonStyle (protocol) - custom interaction behavior & appearance.
.automatic, .bordered, .borderedProminent, .borderless, .plain
.card (tvOS 14), .link (macOS 10.15)
Last updated