Skip to content

Instantly share code, notes, and snippets.

@fxm90
Last active May 26, 2021 06:20
Show Gist options
  • Save fxm90/6afe050ac331d8f719029d7fec87e961 to your computer and use it in GitHub Desktop.
Save fxm90/6afe050ac331d8f719029d7fec87e961 to your computer and use it in GitHub Desktop.
A fully configurable toggle style for SwiftUI.
//
// ColoredToggleStyle.swift
//
// Created by Felix Mau on 29.03.2021.
// Copyright © 2021 Felix Mau. All rights reserved.
//
/// A fully configurable toggle style.
struct ColoredToggleStyle: ToggleStyle {
// MARK: - Config
private enum Config {
static let width: CGFloat = 51
static let height: CGFloat = 31
static let cornerRadius: CGFloat = 16
static let circlePadding: CGFloat = 2
static let animationDuration: TimeInterval = 0.2
static let shadowColor = Color(.sRGBLinear, white: 0, opacity: 0.15)
static let shadowRadius: CGFloat = 2
static let shadowOffset = CGPoint(x: 0, y: 1)
}
// MARK: - Public properties
var onColor: Color = .blue
var offColor: Color = .gray
var thumbColor: Color = .white
// MARK: - Private properties
private var circleShape: some View {
Circle()
.fill(thumbColor)
.aspectRatio(1, contentMode: .fit)
.shadow(color: Config.shadowColor,
radius: Config.shadowRadius,
x: Config.shadowOffset.x,
y: Config.shadowOffset.y)
.padding(Config.circlePadding)
}
// MARK: - Public methods
func makeBody(configuration: Self.Configuration) -> some View {
HStack {
configuration.label
Spacer()
RoundedRectangle(cornerRadius: Config.cornerRadius, style: .circular)
.fill(configuration.isOn ? onColor : offColor)
.frame(width: Config.width, height: Config.height)
.overlay(circleShape, alignment: configuration.isOn ? .trailing : .leading)
.animation(.easeInOut(duration: Config.animationDuration))
}
.onTapGesture {
configuration.isOn.toggle()
}
}
}
@fxm90
Copy link
Author

fxm90 commented May 25, 2021

Example Code

struct ContentView: View {

    // MARK: - Private properties

    @State
    private var isOriginalToggleOn = false

    @State
    private var isCustomToggleOn = false

    // MARK: - Render

    var body: some View {
        List {
            Section(header: Text("Custom Toggle Style")) {
                Toggle("Original Toggle", isOn: $isOriginalToggleOn)

                Toggle("Custom Toggle", isOn: $isCustomToggleOn)
                    .toggleStyle(ColoredToggleStyle())
            }
        }
        .listStyle(InsetGroupedListStyle())
    }
}

The code above will produce the following result.

Off-State On-State
CustomColorToggle--Off CustomColorToggle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment