Created
June 18, 2024 00:25
-
-
Save badrinathvm/fabb741cb35b98ec2c2eed3776217371 to your computer and use it in GitHub Desktop.
Providing option for Custom Style View Modifier
This file contains 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
import SwiftUI | |
// MARK: 2. Create view style protocol | |
protocol CardStyle { | |
associatedtype Body: View | |
typealias Configuration = CardStyleConfiguration | |
func makeBody(configuration: Self.Configuration) -> Self.Body | |
} | |
// MARK: 3. Create style configuration | |
struct CardStyleConfiguration { | |
/// A type-erased content of a `Card`. | |
struct Label: View { | |
init<Content: View>(content: Content) { | |
body = AnyView(content) | |
} | |
var body: AnyView | |
} | |
let label: CardStyleConfiguration.Label | |
} | |
// MARK: 4. Implement base view styles | |
struct DefaultCardStyle: CardStyle { | |
func makeBody(configuration: Configuration) -> some View { | |
configuration.label | |
.font(.title) | |
.padding() | |
.background(RoundedRectangle(cornerRadius: 16).strokeBorder()) | |
} | |
} | |
struct GradientCardStyle: CardStyle { | |
let gradient = AngularGradient( | |
gradient: Gradient(colors: [Color.red, Color.green, Color.blue]), | |
center: .center) | |
func makeBody(configuration: Configuration) -> some View { | |
configuration.label | |
.font(.title) | |
.padding() | |
.background(RoundedRectangle(cornerRadius: 16).stroke(gradient, lineWidth: 1)) | |
} | |
} | |
// MARK: 6. Setup style environment (key + environment value + style eraser) | |
struct AnyCardStyle<S: CardStyle>: CardStyle { | |
private var _makeBody: (Configuration) -> S.Body | |
init(style: S) { | |
_makeBody = { configuration in | |
style.makeBody(configuration: configuration) | |
} | |
} | |
func makeBody(configuration: Configuration) -> S.Body { | |
_makeBody(configuration) | |
} | |
} | |
struct CardStyleKey: EnvironmentKey { | |
static var defaultValue = AnyCardStyle(style: DefaultCardStyle()) | |
} | |
extension EnvironmentValues { | |
var cardStyle: AnyCardStyle<DefaultCardStyle> { | |
get { self[CardStyleKey.self] } | |
set { self[CardStyleKey.self] = newValue } | |
} | |
} | |
// MARK: 7. Define `.xxxStyle(_:)` convenience view modifier | |
extension View { | |
func cardStyle(style: any CardStyle = DefaultCardStyle()) -> some View { | |
self.modifier(CardModifier(style: style)) | |
} | |
} | |
// MARK: 8. Update view to take advantage of environment style | |
struct CardModifier: ViewModifier { | |
var style: any CardStyle | |
public func body(content: Content) -> some View { | |
AnyView(style | |
.makeBody( | |
configuration: CardStyleConfiguration( | |
label: CardStyleConfiguration.Label(content: content) | |
) | |
) | |
) | |
} | |
} | |
// MARK: 9. Enjoy :) | |
struct TestView: View { | |
var body: some View { | |
Button { | |
} label: { | |
Text("Hello") | |
} | |
.cardStyle(style: GradientCardStyle()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment