SkillAgentSearch skills...

OverlayContainer

Non-intrusive iOS UI library to implement overlay based interfaces

Install / Use

/learn @applidium/OverlayContainer
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<H4 align="center"> OverlayContainer is a UI library written in Swift. It makes easier to develop overlay based interfaces, such as the one presented in the Apple Maps, Stocks or Shortcuts apps </H4> <p align="center"> <a href="https://developer.apple.com/"><img alt="Platform" src="https://img.shields.io/badge/platform-iOS-green.svg"/></a> <a href="https://developer.apple.com/swift"><img alt="Swift4" src="https://img.shields.io/badge/language-Swift%204.2-orange.svg"/></a> <a href="https://developer.apple.com/swift"><img alt="Swift5" src="https://img.shields.io/badge/language-Swift%205.0-orange.svg"/></a> <a href="https://cocoapods.org/pods/OverlayContainer"><img alt="CocoaPods" src="https://img.shields.io/cocoapods/v/OverlayContainer.svg?style=flat"/></a> <a href="https://github.com/Carthage/Carthage"><img alt="Carthage" src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat"/></a> <a href="https://github.com/applidium/OverlayContainer/actions"><img alt="Build Status" src="https://github.com/applidium/OverlayContainer/workflows/CI/badge.svg?branch=master"/></a> <a href="https://github.com/applidium/ADOverlayContainer/blob/master/LICENSE"><img alt="License" src="https://img.shields.io/cocoapods/l/OverlayContainer.svg?style=flat"/></a> </p>

⚠️ In iOS 15, consider using UISheetPresentationController before OverlayContainer


OverlayContainer tries to be as lightweight and non-intrusive as possible. The layout and the UI customization are done by you to avoid to corrupt your project.

It perfectly mimics the overlay presented in the Siri Shotcuts app. See this article for details.

  • [x] Unlimited notches
  • [x] Notches modifiable at runtime
  • [x] Adaptive to any custom layouts
  • [x] Rubber band effect
  • [x] Animations and target notch policy fully customizable
  • [x] Unit tested

See the provided examples for help or feel free to ask directly.


<p align="center"> <img src="https://github.com/applidium/ADOverlayContainer/blob/master/Assets/scroll.gif" width="222"> </p>

Usage

Setup

The main component of the library is the OverlayContainerViewController. It defines an area where a view controller, called the overlay view controller, can be dragged up and down, hiding or revealing the content underneath it.

OverlayContainer uses the last view controller of its viewControllers as the overlay view controller. It stacks the other view controllers on top of each other, if any, and adds them underneath the overlay view controller.

A startup sequence might look like this:

let mapsController = MapsViewController()
let searchController = SearchViewController()

let containerController = OverlayContainerViewController()
containerController.delegate = self
containerController.viewControllers = [
    mapsController,
    searchController
]

window?.rootViewController = containerController

Specifing only one view controller is absolutely valid. For instance, in MapsLikeViewController the overlay only covers partially its content.

The overlay container view controller needs at least one notch. Implement OverlayContainerViewControllerDelegate to specify the number of notches wished:

enum OverlayNotch: Int, CaseIterable {
    case minimum, medium, maximum
}

func numberOfNotches(in containerViewController: OverlayContainerViewController) -> Int {
    return OverlayNotch.allCases.count
}

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    heightForNotchAt index: Int,
                                    availableSpace: CGFloat) -> CGFloat {
    switch OverlayNotch.allCases[index] {
        case .maximum:
            return availableSpace * 3 / 4
        case .medium:
            return availableSpace / 2
        case .minimum:
            return availableSpace * 1 / 4
    }
}

Overlay style

The overlay style defines how the overlay view controller will be constrained in the OverlayContainerViewController.

enum OverlayStyle {
    case flexibleHeight
    case rigid
    case expandableHeight // default
}

let overlayContainer = OverlayContainerViewController(style: .rigid)
  • rigid

rigid

The overlay view controller will be constrained with a height equal to the highest notch. The overlay won't be fully visible until the user drags it up to this notch.

  • flexibleHeight

flexible

The overlay view controller will not be height-constrained. It will grow and shrink as the user drags it up and down.

Note though that while the user is dragging the overlay, the overlay's view may perform some extra layout computations. This is specially true for the table views or the collection views : some cells may be dequeued or removed when its frame changes. Try .rigid if you encounter performance issues.

Be careful to always provide a minimum height higher than the intrinsic content of your overlay.

  • expandableHeight

expandable

The overlay view controller will be constrained with a height greater or equal to the highest notch. Its height will be expanded if the overlay goes beyond the highest notch (it could happen if the translation function or the animation controller allow it).

Scroll view support

The container view controller can coordinate the scrolling of a scroll view with the overlay translation.

scrollToTranslation

Use the dedicated delegate method:

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    scrollViewDrivingOverlay overlayViewController: UIViewController) -> UIScrollView? {
    return (overlayViewController as? DetailViewController)?.tableView
}

Or directly set the dedicated property:

let containerController = OverlayContainerViewController()
containerController.drivingScrollView = myScrollView

Make sure to set UIScrollView.alwaysBounceVertical to true so the scroll view will always scroll regardless of its content size.

Pan gesture support

The container view controller detects pan gestures on its own view. Use the dedicated delegate method to check that the specified starting pan gesture location corresponds to a grabbable view in your custom overlay.

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    shouldStartDraggingOverlay overlayViewController: UIViewController,
                                    at point: CGPoint,
                                    in coordinateSpace: UICoordinateSpace) -> Bool {
    guard let header = (overlayViewController as? DetailViewController)?.header else {
        return false
    }
    let convertedPoint = coordinateSpace.convert(point, to: header)
    return header.bounds.contains(convertedPoint)
}

Tracking the overlay

You can track the overlay motions using the dedicated delegate methods:

  • Translation Start

Tells the delegate when the user is about to start dragging the overlay view controller.

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    willStartDraggingOverlay overlayViewController: UIViewController)
  • Translation End

Tells the delegate when the user finishs dragging the overlay view controller with the specified velocity.

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    willEndDraggingOverlay overlayViewController: UIViewController,
                                    atVelocity velocity: CGPoint)
  • Translation In Progress

Tells the delegate when the container is about to move the overlay view controller to the specified notch.

In some cases, the overlay view controller may not successfully reach the specified notch. If the user cancels the translation for instance. Use overlayContainerViewController(_:didMove:toNotchAt:) if you need to be notified each time the translation succeeds.

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    willMoveOverlay overlayViewController: UIViewController,
                                    toNotchAt index: Int)

Tells the delegate when the container has moved the overlay view c

View on GitHub
GitHub Stars1.3k
CategoryDevelopment
Updated16d ago
Forks100

Languages

Swift

Security Score

85/100

Audited on Mar 14, 2026

No findings