SwiftUI Overlay Container is a view Container component for SwiftUI. A customizable, efficient, and convenient view manager.
With a simple configuration, SwiftUI Overlay Container takes care of the basics from view organization, queue processing, transitions, animation, interaction, and display style configuration, allowing developers to focus more on the implementation of the application’s view itself.
The original post was posted on my blog wwww.fatbobman.com
Welcome to subscribe my public account: [Elbow’s Swift Notepad]
history
In the summer of 2020, while adding side sliding menus to Health Note, I found that it was common to come across scenarios in development where you needed to dynamically add another view on top of one view, for example (prompts, ads, floating buttons, novice guides, etc.). Therefore, I have written a component that I hope will help developers accomplish this requirement quickly in SwiftUI. However, due to the limitations of the technology at that time, many of the ideas were not well implemented.
I recently rewrote the component to see if I had improved over time, in addition to implementing functionality that was not previously supported.
You can get the latest version here.
The content of this article is transported directly from the README document for the project.
The motivation
When we need to display new content on top of the view (e.g., pop-up messages, side menus, help hints, etc.), there are many excellent third-party solutions that can help us do this separately, but none of them can address the requirements of different scenarios at the same time. With SwiftUI, it has become so easy to describe views that it is possible to extract the display logic from the above scenarios to create a library that covers more usage scenarios and helps developers organize the display style and interaction logic of views.
Functions and Features
- Support for multiple containers
- Multiple views are supported within a single container
- You can push views to any specified container within or outside the SwiftUI view code
- Configuration of containers can be dynamically modified (except for queue types)
- There are several ways to arrange views within a container
- There are multiple queue types to instruct the container how to display the view
Quick Use Guide
For more information, see the library demo and comments in the source code.
Create a container
Creates a view container on top of the specified view with the size of the attached view:
VStack{
// your view
}
.overlayContainer("containerA", containerConfiguration: AConfiguration())
Copy the code
When no view container is attached to a view:
ViewContainer("containerB", configuration: BConfiguration())
Copy the code
Display the view in the container
In the view container containerA displays the MessageView view
.containerView(in: "containerA", configuration: MessageView(), isPresented: $show, content: ViewConfiguration())
Copy the code
Or use the view manager
struct ContentView1: View {
@Environment(\.overlayContainerManager) var manager
var body: some View {
VStack {
Button("push view in containerB") {
manager.show(view: MessageView(), in: "containerB", using: ViewConfiguration()}}}}Copy the code
Destroys all views in the specified container
struct ContentView1: View {
@Environment(\.overlayContainerManager) var manager
var body: some View {
VStack {
Button("push view in containerB") {
manager.dismissAllView(in: ["containerA"."containerB"], animated: true)}}}}Copy the code
basis
The container
Components that receive and display views. At a minimum, you need to set the container’s name, view display type, and view queue type.
You can set a default view style for the container, and for style attributes not specified by the view, the container’s default Settings are used instead.
Display type
-
stacking
When multiple views are displayed in a container, the views are arranged along the Z-axis. It behaves similarly to ZStack.
-
horizontal
When multiple views are displayed in a container at the same time, the views are arranged along the X-axis. It behaves like HStack.
-
vertical
When multiple views are displayed in a container, the views are arranged along the Y-axis. It behaves like VStack.
View Queue Type
-
multiple
Multiple views can be displayed simultaneously within a container. When the number of views exceeds the maximum number set by the container, the exceeded views are temporarily stored in the waiting queue and replaced one by one after the displayed views are cancelled.
-
oneByOne
Only one view can be displayed in the container at a time. The newly added view will automatically replace the view being displayed.
-
oneByOneWaitFinish
One view can be displayed in the container at a time. A new view can only be displayed if the currently displayed view is destroyed.
Configuration of the container
Container configuration requires setting at least the following properties:
struct MyContainerConfiguration:ContainerConfigurationProtocol{
var displayType: ContainerViewDisplayType = .stacking
var queueType: ContainerViewQueueType = .multiple
}
Copy the code
Other properties that can be set include:
-
delayForShowingNext
Automatically fills the interval for the next view
-
maximumNumberOfViewsInMultipleMode
In Multiple mode, the maximum number of views that can be displayed simultaneously in a container
-
spacing
Indicates the interval between views in vertical and horizontal mode
-
insets
In stacking mode, this value is an embedded value for the view. In horizontal and vertical modes, this value is an embedded value for the view group.
-
Configuration for all other container views (used as the default for container views)
See the Configure Container view below for details
Container environment value
Each container provides an environment value — overlayContainer — for the view inside the container. The view inside the container can use this value to get information about the container (name, size, display type, queue type) and to undo the display.
struct MessageView: View {
@Environment(\.overlayContainer) var container
var body: some View {
RoundedRectangle(cornerRadius: 10)
.frame(width: 300, height: 10)
.overlay(
HStack {
Text("container Name:\(container.containerName)")
Button("Dismiss me"){
container.dismiss()
}
}
)
}
}
Copy the code
Container view
All SwiftUI views can be displayed inside the container. You can configure for similar functionality to create the same views, or to a particular view follow ContainerViewConfigurationProtocol agreement, set separately.
Configuring the Container View
public protocol ContainerViewConfigurationProtocol {
var alignment: Alignment? { get }
var tapToDismiss: Bool? { get }
var backgroundStyle: ContainerBackgroundStyle? { get }
var backgroundTransitionStyle: ContainerBackgroundTransitionStyle { get }
var shadowStyle: ContainerViewShadowStyle? { get }
var dismissGesture: ContainerViewDismissGesture? { get }
var transition: AnyTransition? { get }
var autoDismiss: ContainerViewAutoDismiss? { get }
var disappearAction: (() -> Void)? { get }
var appearAction: (() -> Void)? { get }
var animation: Animation? { get}}Copy the code
-
alignment
Example Set an alignment of a view or view group in a container. In stacking mode, different alignments can be set for each view. In vertical or horizontal mode, all views (view groups) share container alignments.
-
tapToDismiss
Whether it is allowed to undo a view by clicking on the background when backgroundStyle is set for the view.
See the project demo code for details
-
backgroundStyle
Set the background for the container view. Currently supports color, Blur, and customView.
Some versions of the operating system (iOS 14, watchOS) do not support Blur mode. If you want to use Blur in these versions, you can use customView to wrap the other Blur code.
See the project demo code for details
-
backgroundTransitionStyle
Background transitions. Setting opacity to identity cancels transitions.
-
shadowStyle
Add a shadow to the view
-
dismissGesture
Add and cancel gestures to view. Currently, you can click, double click, long press, left swipe, right swipe, up swipe, down swipe, and customize.
Custom gestures to use eraseToAnyGestureForDismiss to erase type.
let gesture = LongPressGesture(minimumDuration: 1, maximumDistance: 5).eraseToAnyGestureForDismiss()
Copy the code
Under tvOS, only long press is supported
See the project demo code for details
-
transition
Transitions of views
-
animation
Animation for view transitions
-
autoDismiss
Whether automatic undo is supported. .seconds(3) Indicates that the view will be automatically cancelled after 3 seconds.
See the project demo code for details
-
disappearAction
Closure that executes after the view is destroyed
-
appearAction
The view displays the previously executed closure in the container
Container manager
The container manager is the bridge between the program code and the container. The consumer invokes specific methods of the container manager to make the specified container perform display views, undo views, and so on.
Container manager environment value
In SwiftUI, view code invokes the container manager with environment values.
struct ContentView1: View {
@Environment(\.overlayContainerManager) var manager
var body: some View {
VStack {
Button("push view in containerB") {
manager.show(view: MessageView(), in: "containerB", using: ViewConfiguration()}}}}Copy the code
The container manager currently provides the following methods:
-
show(view: Content, with ID: UUID? , in container: String, using configuration: ContainerViewConfigurationProtocol, animated: Bool) -> UUID?
Displays the view in the specified container, returning the ID of the view
-
dismiss(view id: UUID, in container: String, animated flag: Bool)
In the specified container, undoes the view with the specified ID
-
dismissAllView(notInclude excludeContainers: [String], onlyShowing: Bool, animated flag: Bool)
Destroys views in all containers except the one specified. When onlyShow is true, only the view being displayed is destroyed.
-
dismissAllView(in containers: [String], onlyShowing: Bool, animated flag: Bool)
Destroys all views in the specified container
Maskable animation
Either by calling the Container Manager directly or using the View Modifier, you can force the transition animation to be unanimated when animated is set to false.
This is useful when dealing with scenarios such as Deep Link.
Used outside the SwiftUI view
If you want to call the ContainerManager outside of the SwiftUI view, you can call the ContainerManager singleton directly:
let manager = ContainerManager.share
manager.show(view: MessageView(), in: "containerB", using: ViewConfiguration())
Copy the code
System requirements
- iOS 14+
- macOS 11+
- tvOS 14+
- watchOS 7+
The installation
The preferred way to install SwiftUIOverlayContainer is through Swift Package Manager.
dependencies: [
.package(url: "https://github.com/fatbobman/SwiftUIOverlayContainer.git", from: "2.0.0")]Copy the code
copyright
This library is distributed under license from MIT. See the LICENSE.
Help and Support
Create Issues to give your comments or suggestions. You can also reach me on Twitter @fatBobman.
The original post was posted on my blog wwww.fatbobman.com
Welcome to subscribe my public account: [Elbow’s Swift Notepad]