Skip to content

Instantly share code, notes, and snippets.

@allenhumphreys
Created October 31, 2022 16:11
Show Gist options
  • Save allenhumphreys/89b920790c97246fb7f96c82bdca8de8 to your computer and use it in GitHub Desktop.
Save allenhumphreys/89b920790c97246fb7f96c82bdca8de8 to your computer and use it in GitHub Desktop.
SwiftUI Custom Button Implementation
//
// ContentView.swift
// GoGoButtons
//
// Created by Allen Humphreys on 10/31/22.
//
import SwiftUI
extension Color {
init(hex: String) {
let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
var int: UInt64 = 0
Scanner(string: hex).scanHexInt64(&int)
let a, r, g, b: UInt64
switch hex.count {
case 3: // RGB (12-bit)
(a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
case 6: // RGB (24-bit)
(a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
case 8: // ARGB (32-bit)
(a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
default:
(a, r, g, b) = (1, 1, 1, 0)
}
self.init(
.sRGB,
red: Double(r) / 255,
green: Double(g) / 255,
blue: Double(b) / 255,
opacity: Double(a) / 255
)
}
}
extension Color {
static var CustomButtonText: Color {
// #2F7185
Color(hex: "#2F7185")
}
static var CustomButtonBackground: Color {
// #2F7185
Color(hex: "#f5f5f5")
}
}
class CustomColor: UIColor {
override func resolvedColor(with traitCollection: UITraitCollection) -> UIColor {
if traitCollection.activeAppearance == .active {
return self
} else {
return .red
}
}
}
struct CustomButton: View {
let configuration: ButtonStyle.Configuration
@Environment(\.isEnabled) private var isEnabled: Bool
@Environment(\.scenePhase) var scenePhase
@Environment(\.isPresented) var isPresented: Bool
@Environment(\.isFocused) var isFocused: Bool
var body: some View {
configuration.label
.padding()
.background(Color.CustomButtonBackground)
.foregroundColor(.CustomButtonText)
.background(in: Capsule())
.animation(.easeOut(duration: 0.2), value: configuration.isPressed)
.onChange(of: isEnabled, perform: { newValue in
print("isEnabled: \(newValue)")
})
.onChange(of: scenePhase) { newValue in
//nothing
print("Phase: \(newValue)")
}
.onChange(of: isPresented) { newValue in
print("isPresented: \(newValue)")
}
.onChange(of: isFocused) { newValue in
print("isFocused: \(newValue)")
}
}
}
struct CustomButtonConfiguration: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
CustomButton(configuration: configuration)
}
}
struct ContentView: View {
@State
var alert: String = ""
@State
private var alertShowing = false
var body: some View {
VStack(alignment: .leading) {
Button("Bordered") {
alert = "Bordered"
alertShowing = true
}
.buttonStyle(.bordered)
.padding([.top, .bottom])
Button("Bordered Prominent") {
alert = "Bordered Prominent"
alertShowing = true
}
.buttonStyle(.borderedProminent)
.padding([.top, .bottom])
Button("Borderless") {
alert = "Borderless"
alertShowing = true
}
.buttonStyle(.borderless)
.padding([.top, .bottom])
Button("Plain") {
alert = "Plain"
alertShowing = true
}
.buttonStyle(.plain)
.padding([.top, .bottom])
Button("Custom Button") {
alert = "Custom"
alertShowing = true
}
.padding([.top, .bottom])
.buttonStyle(CustomButtonConfiguration())
}
.alert(isPresented: $alertShowing, content: {
Alert(
title: Text(alert),
dismissButton: .default(Text("OK"))
)
})
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment