iOS 응용 (SwiftUI)
[iOS - SwiftUI] 뷰를 버튼처럼 만드는 방법 (DragGesture, pressed color 효과, 커스텀 버튼)
jake-kim
2024. 10. 14. 01:43
뷰를 버튼처럼 만드는 방법
- 일반 SwiftUI의 버튼은 Button(action:label:)형태이며, presssed color는 label부분이 투명해지는 효과가 디폴트로 들어간 상태
(코드)
struct ContentView: View {
@State private var isPressed = false
@State private var isChecked = false
var body: some View {
VStack {
normalButton
}
}
@ViewBuilder
private var normalButton: some View {
Button(action: {
isChecked.toggle()
}, label: {
HStack(spacing: 6) {
Image(systemName: isChecked ? "circle.fill" : "circle")
Text("button")
}
})
.background(isPressed ? Const.color : Const.pressedColor)
}
}
- Button을 안쓰고 싶거나 pressed color를 주는 커스텀 버튼으로 만들고 싶은 경우?
- 일반 뷰에다 .gesture()로 제스처를 등록하고, 사용자가 누르고 있는 동안은 색상이 변경되어 보여야하므로 pressed 효과를 주기 위해 DragGesture를 활용
- drag의 상태가 onChnaged인 경우에는 isPressed를 true로 넣고, end상태인 경우 isPressed를 false로 세팅
커스텀 버튼 만들기
- @ViewBuilder로 선언
@ViewBuilder
private var customButton: some View {
}
- 이미지와 Text가 들어가 있는 버튼을 만들어야 하기 때문에 HStack 사용
@State private var isChecked = false
@State private var isPressed = false
HStack(spacing: 6) {
Image(systemName: isChecked ? "circle.fill" : "circle")
Text("button")
}
.background(isPressed ? Const.color : Const.pressedColor)
- 여기에 DragGesture를 등록
- 단순히 한 점을 클릭해도 동작해야하므로 minimumDistance를 0으로 설정
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in
isPressed = true
}
.onEnded { _ in
isPressed = false
isChecked.toggle()
}
)
완성)
전체 코드)
import SwiftUI
struct ContentView: View {
@State private var isPressed = false
@State private var isChecked = false
var body: some View {
VStack {
normalButton
customButton
}
}
@ViewBuilder
private var normalButton: some View {
Button(action: {
isChecked.toggle()
}, label: {
HStack(spacing: 6) {
Image(systemName: isChecked ? "circle.fill" : "circle")
Text("button")
}
})
.background(isPressed ? Const.color : Const.pressedColor)
}
@ViewBuilder
private var customButton: some View {
HStack(spacing: 6) {
Image(systemName: isChecked ? "circle.fill" : "circle")
Text("button")
}
.background(isPressed ? Const.color : Const.pressedColor)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { _ in
isPressed = true
}
.onEnded { _ in
isPressed = false
isChecked.toggle()
}
)
}
}
#Preview {
ContentView()
}
private enum Const {
static let color = Color.gray
static let pressedColor = Self.color.opacity(0.8)
}