-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use frame modifier inside relative modifier (#49)
- Loading branch information
Showing
2 changed files
with
142 additions
and
135 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import SwiftUI | ||
|
||
#if DEBUG | ||
// still in development | ||
|
||
#Preview("Using Aligment guide") { | ||
|
||
Rectangle() | ||
.frame(width: 50, height: 50) | ||
.anchoring { | ||
Circle() | ||
.fill(.blue) | ||
} | ||
.background(Color.purple) | ||
} | ||
|
||
extension View { | ||
|
||
internal func anchoring(@ViewBuilder content: () -> some View) -> some View { | ||
overlay(alignment: .topTrailing) { | ||
content() | ||
.alignmentGuide(.top) { d in | ||
d[.top] + d.height / 2 | ||
} | ||
.alignmentGuide(.trailing) { d in | ||
d[.trailing] - d.width / 2 | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
#endif |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,169 +1,143 @@ | ||
import SwiftUI | ||
|
||
public enum RelativeHorizontalPosition { | ||
case left | ||
case center | ||
case right | ||
} | ||
|
||
public enum RelativeVerticalPosition { | ||
case top | ||
case center | ||
case bottom | ||
} | ||
|
||
/// A container view that places the content in the specified position. | ||
/// A useful case will be placing the content on the corner of the parent view. | ||
@available(*, deprecated, message: "Use modifier instead") | ||
public struct RelativeView<Content: View>: View { | ||
|
||
public let content: Content | ||
public let vertical: RelativeVerticalPosition | ||
public let horizontal: RelativeHorizontalPosition | ||
|
||
public init( | ||
vertical: RelativeVerticalPosition, | ||
horizontal: RelativeHorizontalPosition, | ||
@ViewBuilder content: () -> Content | ||
) { | ||
self.vertical = vertical | ||
self.horizontal = horizontal | ||
self.content = content() | ||
} | ||
|
||
public var body: some View { | ||
|
||
let horizontalContent: some View = HStack { | ||
switch horizontal { | ||
case .left: | ||
content | ||
Spacer(minLength: 0) | ||
case .center: | ||
content | ||
case .right: | ||
Spacer(minLength: 0) | ||
content | ||
} | ||
} | ||
|
||
VStack { | ||
switch vertical { | ||
case .top: | ||
horizontalContent | ||
Spacer(minLength: 0) | ||
case .center: | ||
horizontalContent | ||
case .bottom: | ||
Spacer(minLength: 0) | ||
horizontalContent | ||
} | ||
} | ||
|
||
} | ||
} | ||
|
||
/// like align-self | ||
public struct RelativeLayoutModifier: ViewModifier { | ||
/// deprecated | ||
public struct RelativeLayoutModifier { | ||
|
||
public enum HorizontalPosition { | ||
case leading | ||
@available(*, unavailable) | ||
case center | ||
case trailing | ||
} | ||
|
||
public enum VerticalPosition { | ||
case top | ||
@available(*, unavailable) | ||
case center | ||
case bottom | ||
} | ||
|
||
public let vertical: VerticalPosition | ||
public let horizontal: HorizontalPosition | ||
} | ||
|
||
public init( | ||
vertical: VerticalPosition, | ||
horizontal: HorizontalPosition | ||
) { | ||
self.vertical = vertical | ||
self.horizontal = horizontal | ||
} | ||
extension View { | ||
|
||
public func body(content: Content) -> some View { | ||
let horizontalContent: some View = HStack { | ||
/** | ||
* Lays out the view and positions it within the layout bounds according to vertical and horizontal positional specifiers. | ||
* Can position the child at any of the 4 corners, or the middle of any of the 4 edges, as well as the center - similar to "9-part" image areas. | ||
*/ | ||
@available(*, deprecated, message: "use relative(alignment: )") | ||
public func relative( | ||
vertical: RelativeLayoutModifier.VerticalPosition, | ||
horizontal: RelativeLayoutModifier.HorizontalPosition | ||
) -> some View { | ||
|
||
return self.relative(alignment: .init( | ||
horizontal: { | ||
switch horizontal { | ||
case .center: | ||
return .center | ||
case .leading: | ||
return .leading | ||
case .trailing: | ||
return .trailing | ||
} | ||
}(), | ||
vertical: { | ||
switch vertical { | ||
case .center: | ||
return .center | ||
case .top: | ||
return .top | ||
case .bottom: | ||
return .bottom | ||
} | ||
}() | ||
) | ||
) | ||
} | ||
|
||
@available(*, deprecated, message: "use relative(alignment: )") | ||
public func relative( | ||
horizontal: RelativeLayoutModifier.HorizontalPosition | ||
) -> some View { | ||
|
||
return self.relative(horizontalAlignment: { | ||
switch horizontal { | ||
case .leading: | ||
content | ||
Spacer(minLength: 0) | ||
case .center: | ||
content | ||
return .center | ||
case .leading: | ||
return .leading | ||
case .trailing: | ||
Spacer(minLength: 0) | ||
content | ||
return .trailing | ||
} | ||
} | ||
|
||
VStack { | ||
}() | ||
) | ||
} | ||
|
||
@available(*, deprecated, message: "use relative(alignment: )") | ||
public func relative( | ||
vertical: RelativeLayoutModifier.VerticalPosition | ||
) -> some View { | ||
|
||
return self.relative(verticalAlignment: { | ||
switch vertical { | ||
case .top: | ||
horizontalContent | ||
Spacer(minLength: 0) | ||
case .center: | ||
horizontalContent | ||
return .center | ||
case .top: | ||
return .top | ||
case .bottom: | ||
Spacer(minLength: 0) | ||
horizontalContent | ||
} | ||
} | ||
return .bottom | ||
} | ||
}() | ||
) | ||
} | ||
|
||
} | ||
|
||
extension View { | ||
|
||
/** | ||
* Lays out the view and positions it within the layout bounds according to vertical and horizontal positional specifiers. | ||
* Can position the child at any of the 4 corners, or the middle of any of the 4 edges, as well as the center - similar to "9-part" image areas. | ||
*/ | ||
|
||
public func relative( | ||
vertical: RelativeLayoutModifier.VerticalPosition = .center, | ||
horizontal: RelativeLayoutModifier.HorizontalPosition = .center | ||
) -> some View { | ||
self.modifier(RelativeLayoutModifier(vertical: vertical, horizontal: horizontal)) | ||
alignment: Alignment | ||
) -> some View { | ||
self.frame( | ||
maxWidth: .infinity, | ||
maxHeight: .infinity, | ||
alignment: alignment | ||
) | ||
} | ||
|
||
|
||
public func relative( | ||
horizontalAlignment: HorizontalAlignment | ||
) -> some View { | ||
self.frame(maxWidth: .infinity, alignment: .init(horizontal: horizontalAlignment, vertical: .center)) | ||
} | ||
|
||
public func relative( | ||
verticalAlignment: VerticalAlignment | ||
) -> some View { | ||
self.frame(maxHeight: .infinity, alignment: .init(horizontal: .center, vertical: verticalAlignment)) | ||
} | ||
|
||
public func relative( | ||
horizontalAlignment: HorizontalAlignment, | ||
verticalAlignment: VerticalAlignment | ||
) -> some View { | ||
self.frame( | ||
maxWidth: .infinity, | ||
maxHeight: .infinity, | ||
alignment: .init(horizontal: horizontalAlignment, vertical: verticalAlignment) | ||
) | ||
} | ||
|
||
} | ||
|
||
enum Preview_AnchorView: PreviewProvider { | ||
|
||
static var previews: some View { | ||
#Preview { | ||
HStack(alignment: .top) { | ||
Rectangle() | ||
.frame(width: 50, height: 50) | ||
.overlay( | ||
RelativeView(vertical: .top, horizontal: .right) { | ||
Circle() | ||
.foregroundColor(.red) | ||
.frame(width: 20, height: 20) | ||
} | ||
.offset(x: 10, y: -10) | ||
) | ||
|
||
.frame(width: 100, height: 100) | ||
|
||
Rectangle() | ||
.frame(width: 50, height: 50) | ||
.overlay( | ||
Circle() | ||
.foregroundColor(.red) | ||
.frame(width: 20, height: 20) | ||
.relative(vertical: .top, horizontal: .trailing) | ||
.offset(x: 10, y: -10) | ||
) | ||
|
||
HStack { | ||
Text("A") | ||
Text("B") | ||
Text("C") | ||
} | ||
.environment(\.layoutDirection, .rightToLeft) | ||
|
||
} | ||
.foregroundColor(.red) | ||
.relative(verticalAlignment: .center) | ||
|
||
} | ||
.background(Color.green) | ||
} |