Last active
December 19, 2024 21:18
-
-
Save mjmsmith/040ffb4a8536b61bf479ad5b0abeea6e to your computer and use it in GitHub Desktop.
Padding modifier for SwiftUI views.
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
// NOTE: Nil values implicitly or explicitly passed as arguments to padding() are ignored. | |
// This differs from the built-in SwiftUI version: | |
// | |
// view.padding(trailing: nil) // has no effect | |
// view.padding(.trailing, nil) // resets to default | |
// | |
// See below for a version that matches the built-in behavior. | |
extension View { | |
func padding(horizontal: CGFloat? = nil, vertical: CGFloat? = nil, | |
top: CGFloat? = nil, leading: CGFloat? = nil, | |
bottom: CGFloat? = nil, trailing: CGFloat? = nil) -> some View { | |
modifier(PaddingModifier(horizontal: horizontal, vertical: vertical, | |
top: top, leading: leading, | |
bottom: bottom, trailing: trailing)) | |
} | |
} | |
private struct PaddingModifier: ViewModifier { | |
let horizontal: CGFloat? | |
let vertical: CGFloat? | |
let top: CGFloat? | |
let leading: CGFloat? | |
let bottom: CGFloat? | |
let trailing: CGFloat? | |
func body(content: Content) -> some View { | |
content | |
.modifier(EdgePaddingModifier(.horizontal, horizontal)) | |
.modifier(EdgePaddingModifier(.vertical, vertical)) | |
.modifier(EdgePaddingModifier(.top, top)) | |
.modifier(EdgePaddingModifier(.leading, leading)) | |
.modifier(EdgePaddingModifier(.bottom, bottom)) | |
.modifier(EdgePaddingModifier(.trailing, trailing)) | |
} | |
} | |
private struct EdgePaddingModifier: ViewModifier { | |
let edge: Edge.Set | |
let inset: CGFloat? | |
init(_ edge: Edge.Set, _ inset: CGFloat?) { | |
self.edge = edge | |
self.inset = inset | |
} | |
func body(content: Content) -> some View { | |
if let inset { | |
content.padding(edge, inset) | |
} | |
else { | |
content | |
} | |
} | |
} | |
// This version uses .nan instead of nil for default arguments to padding() so that | |
// it matches the built-in behavior: | |
// | |
// view.padding(trailing: nil) // resets to default | |
// view.padding(.trailing, nil) // resets to default | |
// | |
extension View { | |
func padding(horizontal: CGFloat? = .nan, vertical: CGFloat? = .nan, | |
top: CGFloat? = .nan, leading: CGFloat? = .nan, | |
bottom: CGFloat? = .nan, trailing: CGFloat? = .nan) -> some View { | |
modifier(PaddingModifier(horizontal: horizontal, vertical: vertical, | |
top: top, leading: leading, | |
bottom: bottom, trailing: trailing)) | |
} | |
} | |
private struct PaddingModifier: ViewModifier { | |
let horizontal: CGFloat? | |
let vertical: CGFloat? | |
let top: CGFloat? | |
let leading: CGFloat? | |
let bottom: CGFloat? | |
let trailing: CGFloat? | |
func body(content: Content) -> some View { | |
content | |
.modifier(EdgePaddingModifier(.horizontal, horizontal)) | |
.modifier(EdgePaddingModifier(.vertical, vertical)) | |
.modifier(EdgePaddingModifier(.top, top)) | |
.modifier(EdgePaddingModifier(.leading, leading)) | |
.modifier(EdgePaddingModifier(.bottom, bottom)) | |
.modifier(EdgePaddingModifier(.trailing, trailing)) | |
} | |
} | |
private struct EdgePaddingModifier: ViewModifier { | |
let edge: Edge.Set | |
let inset: CGFloat? | |
init(_ edge: Edge.Set, _ inset: CGFloat?) { | |
self.edge = edge | |
self.inset = inset | |
} | |
func body(content: Content) -> some View { | |
if inset?.isNaN ?? false { | |
content | |
} | |
else { | |
content.padding(edge, inset) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment