OverlapStack
is a SwiftUI library that simplifies creating overlapping layouts. With OverlapHStack
and OverlapVStack
, you can arrange content in customizable horizontal or vertical overlapping stacks with full control over alignment, arrangement, and spacing.
- Create overlapping layouts with ease. -Fully customizable alignment, arrangement, and spacing. -Supports manual offsets for fine-tuned control.
To run the example project, clone the repo, and run pod install
from the Example directory first.
- Swift 5.5 or higher
- iOS 16.0 or higher
- MacOS 13.0 or higher
- TVOS 16.0 or higher
- WatchOS 8.0 or higher
- Xcode 14 or higher
You can easily install OverlapStack via CocoaPods. Add the following line to your Podfile:
pod 'OverlapStack', '~> 1.0'
To install using Xcode's Swift Package Manager, follow these steps:
- Go to File > Swift Package > Add Package Dependency
- Enter the URL: https://github.com/hainayanda/OverlapStack.git
- Choose Up to Next Major for the version rule and set the version to 1.0.0.
- Click "Next" and wait for the package to be fetched.
If you prefer using Package.swift, add OverlapStack as a dependency in your Package.swift file:
dependencies: [
.package(url: "https://github.com/hainayanda/OverlapStack.git", .upToNextMajor(from: "1.0.0"))
]
Then, include it in your target:
.target(
name: "MyModule",
dependencies: ["OverlapStack"]
)
The OverlapVStack
arranges its subviews in a vertical overlapping layout:
OverlapVStack {
Text("Card 1")
.frame(width: 240, height: 140)
.background(Color.blue)
.cornerRadius(10)
Text("Card 2")
.frame(width: 270, height: 160)
.background(Color.green)
.cornerRadius(10)
Text("Card 3")
.frame(width: 300, height: 180)
.background(Color.red)
.cornerRadius(10)
}
You will end up with a view like this:
You can pass an OverlapVStackAlignment
and VerticalOverlapArrangement
to OverlapVStack
init parameters to configure the View arrangement to meet your need:
public init(
alignment: OverlapVStackAlignment = .centered,
arrangement: VerticalOverlapArrangement = .stackedFromTop,
defaultOffset: CGFloat = 24,
@ViewBuilder content: @escaping () -> Content) {
// code
}
While the defaultOffset
is the offset between one overlapped stacked view to another. You can assign the offset manually by the view itself by calling the overlapOffset
method in view:
OverlapVStack {
Text("Card 1")
.frame(width: 240, height: 140)
.background(Color.blue)
.cornerRadius(10)
.overlapOffset(12) // use 12 as the offset to the next view
// code
}
Other than overlap offset, there is another offset that can be customized which is alignment offset, which is the offset of the view with its base alignment that can be assigned by calling the overlapAlignmentOffset
method in view:
OverlapVStack {
Text("Card 1")
.frame(width: 240, height: 140)
.background(Color.blue)
.cornerRadius(10)
.overlapOffset(12) // use 12 as the offset to the next view
// code
}
Both overlap offset and alignment offset can be described by this diagram:
The OverlapVStack
arranges its subviews in a vertical overlapping layout:
OverlapHStack {
Text("Card 1")
.frame(width: 240, height: 140)
.background(Color.blue)
.cornerRadius(10)
Text("Card 2")
.frame(width: 270, height: 160)
.background(Color.green)
.cornerRadius(10)
Text("Card 3")
.frame(width: 300, height: 180)
.background(Color.red)
.cornerRadius(10)
}
You will end up with a view like this:
You can pass an OverlapHStackAlignment
and HorizontalOverlapArrangement
to OverlapHStack
init parameters to configure the View arrangement to meet your need:
public init(
alignment: OverlapVStackAlignment = .centered,
arrangement: HorizontalOverlapArrangement = .stackedFromTrailing,
defaultOffset: CGFloat = 24,
@ViewBuilder content: @escaping () -> Content) {
// code
}
While the defaultOffset
is the offset between one overlapped stacked view to another. Similar to OverlapVStack
, you can assign the offset manually by the view itself by calling the overlapOffset
method in view:
OverlapHStack {
Text("Card 1")
.frame(width: 240, height: 140)
.background(Color.blue)
.cornerRadius(10)
.overlapOffset(12) // use 12 as the offset to the next view
// code
}
Similar to OverlapVStack
, there is another offset that can be customized which is alignment offset, which is the offset of the view with its base alignment that can be assigned by calling the overlapAlignmentOffset
method in view:
OverlapHStack {
Text("Card 1")
.frame(width: 240, height: 140)
.background(Color.blue)
.cornerRadius(10)
.overlapOffset(12) // use 12 as the offset to the next view
// code
}
Both overlap offset and alignment offset can be described by this diagram:
You can expand the overlapping view by calling the method expandOverlap
on the view and passing true
for expanding and false
for default:
OverlapVStack {
Text("Card 1")
.frame(width: 240, height: 140)
.background(Color.blue)
.cornerRadius(10)
.expandOverlap(true, trailing: 12) // expand the view and add trailing spacing 12 to the next view
// code
}
Then it will be expanded like this:
VStack | HStack |
---|---|
![]() |
![]() |
Put them in ScrollView
and change the value using animation, you can end up with something like this:
VStack | HStack |
---|---|
![]() |
![]() |
Contributions are welcome! Please follow the guidelines in the CONTRIBUTING.md file.
OverlapStack is available under the MIT license. For more information, see the LICENSE file.
This project is maintained by Nayanda Haberty.