2025๋…„ 04์›” 19์ผ

๐ŸŒŸ SwiftUI์—์„œ ๋‚˜๋งŒ์˜ ํ† ๊ธ€ ๋งŒ๋“ค๊ธฐ

CustomToggleStyle ๊ตฌํ˜„ (macOS ์•ฑ์šฉ)

SwiftUI๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ์†์‰ฝ๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ macOS ์•ฑ์—์„œ ๊ธฐ๋ณธ Toggle ๋Œ€์‹  ์ง์ ‘ ์Šคํƒ€์ผ์„ ์ •์˜ํ•ด ๋‚˜๋งŒ์˜ ๋””์ž์ธ์„ ์ ์šฉํ•ด๋ณด๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.


โœ… ๋ชฉํ‘œ

macOS์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ปค์Šคํ…€ ํ† ๊ธ€ ์Šคํƒ€์ผ์„ ๋งŒ๋“ค์–ด์„œ, ๊ธฐ์กด์˜ ์Šค์œ„์น˜ ์Šคํƒ€์ผ์ด ์•„๋‹Œ ์ง์‚ฌ๊ฐํ˜• ์•ˆ์— ์›์ด ์ขŒ์šฐ๋กœ ์›€์ง์ด๋Š” ํ† ๊ธ€์„ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


๐Ÿ“Œ ์ „์ฒด ์ฝ”๋“œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ

import SwiftUI

struct CustomToggleStyle: ToggleStyle {
   func makeBody(configuration: Configuration) -> some View {
      HStack {
         configuration.label
         Rectangle()
            .foregroundColor(configuration.isOn ? .green : Color(hex: "#468284"))
            .frame(width: 40, height: 20)
            .cornerRadius(10)
            .overlay(
               Circle()
                  .foregroundColor(.white)
                  .padding(.all, 3)
                  .offset(x: configuration.isOn ? 10 : -10)
            )
            .onTapGesture {
               configuration.isOn.toggle()
            }
      }
   }
}

๐Ÿงฉ ์ฝ”๋“œ ๊ตฌ์„ฑ ์ƒ์„ธ ์„ค๋ช…

1. ToggleStyle ํ”„๋กœํ† ์ฝœ ์ฑ„ํƒ

ToggleStyle์„ ์ฑ„ํƒํ•˜๋ฉด Toggle์˜ ์‹œ๊ฐ์  ํ‘œํ˜„์„ ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. makeBody(configuration: ) ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•ฉ๋‹ˆ๋‹ค.

2. configuration.label

Toggle์— ์ „๋‹ฌ๋œ ๋ผ๋ฒจ์„ HStack์˜ ์™ผ์ชฝ์— ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด “์•Œ๋ฆผ ์„ค์ •” ๊ฐ™์€ ํ…์ŠคํŠธ๊ฐ€ ์—ฌ๊ธฐ์— ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

3. ์ง์‚ฌ๊ฐํ˜• ๋ฐฐ๊ฒฝ (Rectangle)

– ํฌ๊ธฐ : 40 x 20
– ์ƒ‰์ƒ : isOn ์ƒํƒœ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ํ‘œํ˜„
์ผœ์ง (true) : ์ดˆ๋ก์ƒ‰ (.green)
๊บผ์ง (false) : ์Šคํ‹ธ๋ธ”๋ฃจ ๊ณ„์—ด (#4682B4)
– ๋‘ฅ๊ทผ ๋ชจ์„œ๋ฆฌ : cornerRadius(10) ์œผ๋กœ ๋ฒ„ํŠผ์ฒ˜๋Ÿผ ๋ณด์ด๋„๋ก ์ฒ˜๋ฆฌ

4. ์›ํ˜• ์Šฌ๋ผ์ด๋” (Circle)

– ํฐ์ƒ‰ ์›์ด ๋‚ด๋ถ€์— ์œ„์น˜ํ•ด ์žˆ๊ณ , .offset(x:)์„ ์‚ฌ์šฉํ•ด ์ขŒ์šฐ ์ด๋™
isOn == true ์ด๋ฉด ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™
isOn == false ์ด๋ฉด ์™ผ์ชฝ์œผ๋กœ ์ด๋™
– .padding(.all, 3) ์œผ๋กœ ์–‘ ๋์— ์—ฌ๋ฐฑ ํ™•๋ณด
– overlay๋กœ Rectangle ์œ„์— ๋ง์”Œ์›€

5. ์ œ์Šค์ฒ˜ ์ถ”๊ฐ€ (onTapGesture)
์‚ฌ์šฉ์ž๊ฐ€ Rectangle์„ ํด๋ฆญํ•˜๋ฉด isOn ์ƒํƒœ๋ฅผ ๋ฐ˜์ „์‹œํ‚ค๋„๋ก ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰ ์‹ค์ œ ๋™์ž‘์€ ์ด ์ œ์Šค์ฒ˜๋กœ ํŠธ๋ฆฌ๊ฑฐ ๋ฉ๋‹ˆ๋‹ค.


๐Ÿงช ์‹ค์ œ ์‚ฌ์šฉ ์˜ˆ์‹œ

// 3.์ค‘๋ณต์ฒดํฌ ์Šฌ๋ผ์ด๋”
Toggle(NSLocalizedString("DUPLICATE_CHECK", comment: "์ค‘๋ณต์ฒดํฌ"), isOn: $viewModel.isDuplicate(Enabled)
   .toggleStyle(CustomToggleStyle())

๐Ÿ’ก ์ •๋ฆฌ

SwiftUI์˜ ToggleStyle์„ ํ™œ์šฉํ•˜๋ฉด ๋งค์šฐ ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉ์ž ์ •์˜ ํ† ๊ธ€ UI๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ์˜ˆ์ œ์ฒ˜๋Ÿผ macOS ์•ฑ์—์„œ๋„ ์ง๊ด€์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด์„ธ์š”!!