Created
March 17, 2025 21:03
-
-
Save juanarzola/580f4428ca0e4e2fe7a831b23767cd14 to your computer and use it in GitHub Desktop.
Exposes tintColor in the dimmed state to SwiftUI. Use this to adapt any non-accentColor color to the dimmed state.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// EnvironmentDimmedTintColorViewModifier.swift | |
// Learn | |
// | |
// Created by Juan Arzola on 3/17/25. | |
// Copyright © 2025 Juan Arzola. All rights reserved. | |
// | |
import SwiftUI | |
import UIKit | |
public extension View { | |
/** | |
* Exposes to the environment the tint color of the view at the "dimmed" state. While Color.accentColor automatically adapts | |
* to this color, no other color does. This \.dimmedTintColor environment value helps you adapt any other color to the dimmed state when as well. | |
*/ | |
func environmentDimmedTintColor() -> some View { | |
modifier(EnvironmentDimmedTintColorViewModifier()) | |
} | |
} | |
private struct EnvironmentDimmedTintColorViewModifier: ViewModifier { | |
@State private var dimmedTintColor: Color? = nil | |
func body(content: Content) -> some View { | |
content | |
.overlay( | |
TintColorObserverRepresentable( | |
originalTint: UIColor(Color.accentColor), | |
dimmedTintColor: $dimmedTintColor | |
) | |
.frame(width: 0, height: 0) | |
.accessibilityHidden(true) | |
.allowsHitTesting(false) | |
) | |
.environment(\.dimmedTintColor, dimmedTintColor) | |
} | |
} | |
private class TintColorObserver: UIView { | |
var originalTint: UIColor? = nil | |
var dimmedTintColor: Binding<Color?> = .constant(nil) | |
override func tintColorDidChange() { | |
super.tintColorDidChange() | |
if let tintColor { | |
if originalTint != tintColor { | |
Task { @MainActor in | |
dimmedTintColor.wrappedValue = Color(tintColor) | |
} | |
} | |
} else if dimmedTintColor.wrappedValue != nil { | |
Task { @MainActor in | |
dimmedTintColor.wrappedValue = nil | |
} | |
} | |
} | |
} | |
private struct TintColorObserverRepresentable: UIViewRepresentable { | |
var originalTint: UIColor? | |
var dimmedTintColor: Binding<Color?> | |
func makeUIView(context: Context) -> TintColorObserver { | |
let view = TintColorObserver() | |
view.originalTint = originalTint | |
view.dimmedTintColor = dimmedTintColor.projectedValue | |
return view | |
} | |
func updateUIView(_ uiView: TintColorObserver, context: Context) { | |
uiView.originalTint = originalTint | |
} | |
} | |
// MARK: - Environment | |
private struct DimmedTintColorKey: EnvironmentKey { | |
static let defaultValue: Color? = nil | |
} | |
public extension EnvironmentValues { | |
var dimmedTintColor: Color? { | |
get { self[DimmedTintColorKey.self] } | |
set { self[DimmedTintColorKey.self] = newValue } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment