[SwiftUI] ButtonStyle

Junyoung Park·2022년 8월 20일
0

SwiftUI

목록 보기
30/136
post-thumbnail
post-custom-banner

How to create custom ButtonStyles in SwiftUI | Advanced Learning #2

ButtonStyle

구현 목표

  • ButtonStyle 프로토콜을 사용, 커스텀 버튼 스타일 구현
  • 뷰 익스텐션을 통해 버튼 스타일 적용 함수화
  • 파라미터를 통해 특정 프로퍼티를 전달, 디폴트 값 설정하기
  • 뷰 모디파이어와 함께 버튼 스타일 확장

구현 태스크

  1. ButtonStyle 프로토콜을 준수하는 버튼 스타일 구조체 구현
  2. extension 상 버튼 스타일을 구현, 리턴하는 함수 구현

핵심 코드

import SwiftUI

struct PressableButtonStyle: ButtonStyle {
    let scaledAmount: CGFloat
    
    init(scaledAmount: CGFloat = 0.9) {
        self.scaledAmount = scaledAmount
    }
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? scaledAmount : 1.0)
//            .brightness(configuration.isPressed ? 0.1 : 0)
            .opacity(configuration.isPressed ? 0.9 : 1.0)
    }
}

extension View {
    func withPressableStyle(_ scaledAmount: CGFloat = 0.9) -> some View {
        buttonStyle(PressableButtonStyle(scaledAmount: scaledAmount))
    }
}
  • configuration을 통해 버튼을 '눌렀을 때' (isPressed) 어떤 모습이 될지 설정할 수 있다. opacity, scaleEffect, brightness 등 다양한 라벨 이펙트를 줄 수 있다.
  • 뷰 모디파이어와 마찬가지로 익스텐션을 통해 해당 버튼 스타일을 함수화할 수 있다.

소스 코드

import SwiftUI

struct PressableButtonStyle: ButtonStyle {
    let scaledAmount: CGFloat
    
    init(scaledAmount: CGFloat = 0.9) {
        self.scaledAmount = scaledAmount
    }
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? scaledAmount : 1.0)
//            .brightness(configuration.isPressed ? 0.1 : 0)
            .opacity(configuration.isPressed ? 0.9 : 1.0)
    }
}

extension View {
    func withPressableStyle(_ scaledAmount: CGFloat = 0.9) -> some View {
        buttonStyle(PressableButtonStyle(scaledAmount: scaledAmount))
    }
}

struct ButtonStyleBootCamp: View {
    var body: some View {
        VStack {
            Button(action: {
                
            }, label: {
                Text("CLICK ME")
                    .font(.headline)
                    .foregroundColor(.white)
                    .frame(height: 55)
                    .frame(maxWidth: .infinity)
                    .background(.blue)
                    .cornerRadius(10)
                    .shadow(color: Color.blue.opacity(0.3), radius: 10, x: 0.0, y: 10)
            })
            .buttonStyle(PressableButtonStyle())
            Button(action: {
                
            }, label: {
                Text("CLICK ME")
                    .font(.headline)
                    .foregroundColor(.white)
                    .frame(height: 55)
                    .frame(maxWidth: .infinity)
                    .background(.blue)
                    .cornerRadius(10)
                    .shadow(color: Color.blue.opacity(0.3), radius: 10, x: 0.0, y: 10)
            })
            .buttonStyle(PressableButtonStyle(scaledAmount: 0.7))
            Button(action: {
                
            }, label: {
                Text("CLICK ME")
                    .withDefaultButtonFormmating(.red)
            })
            .withPressableStyle(0.5)
        }
        .padding(40)
    }
}
  • 뷰 모디파이어와 함께 버튼 스타일 구현 시 확장성이 매우 뛰어남

구현 화면

profile
JUST DO IT
post-custom-banner

0개의 댓글