Last active
December 19, 2022 05:40
-
-
Save shnhrrsn/0df64c41c78ae63d188654d0c99bb1ee to your computer and use it in GitHub Desktop.
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 | |
/// Implementation of `Layout` that aligns subviews relative it their `anchor` value | |
/// | |
/// Considerations before using: | |
/// * Sizing is not taken into account | |
/// * No stacking is provided if multiple subviews are anchored to the same position | |
/// * Subviews will be able to overlap if anchored closely together and they're both large enough | |
public struct AnchorLayout: Layout { | |
public init() { } | |
public func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize { | |
proposal.replacingUnspecifiedDimensions() | |
} | |
public func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) { | |
for subview in subviews { | |
let anchor = subview[AnchorValue.self] | |
subview.place( | |
at: .init( | |
x: bounds.minX + (bounds.size.width * anchor.x), | |
y: bounds.minY + (bounds.size.height * anchor.y) | |
), | |
anchor: anchor, | |
proposal: proposal | |
) | |
} | |
} | |
} | |
private struct AnchorValue: LayoutValueKey { | |
static let defaultValue = UnitPoint.center | |
} | |
extension View { | |
public func anchor(_ anchor: UnitPoint) -> some View { | |
self.layoutValue(key: AnchorValue.self, value: anchor) | |
} | |
} | |
struct AnchorLayout_Previews: PreviewProvider { | |
static var previews: some View { | |
ZStack { | |
Color.yellow.frame(width: 5.0) | |
Color.yellow.frame(height: 5.0) | |
AnchorLayout { | |
Group { | |
Color.red.anchor(.topLeading) | |
Color.green.anchor(.top) | |
Color.blue.anchor(.topTrailing) | |
Color.pink.anchor(.leading) | |
Color.mint.anchor(.center) | |
Color.indigo.anchor(.trailing) | |
Color.orange.anchor(.bottomLeading) | |
Color.brown.anchor(.bottom) | |
Color.purple.anchor(.bottomTrailing) | |
Color.gray.anchor(.init(x: 0.25, y: 0.25)) | |
}.frame(width: 50.0, height: 50.0).cornerRadius(20.0) | |
}.padding(5.0) | |
} | |
.frame(width: 300.0, height: 500.0) | |
.previewLayout(.sizeThatFits) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment