Non-intrusive iOS UI library to implement overlay based interfaces

Overview

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

Platform Swift4 Swift5 CocoaPods Carthage Build Status License


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.

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

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



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 controller to the specified notch.

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

Tells the delegate whenever the overlay view controller is about to be translated.

The delegate typically implements this method to coordinate changes alongside the overlay view controller's translation.

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    willTranslateOverlay overlayViewController: UIViewController,
                                    transitionCoordinator: OverlayContainerTransitionCoordinator)

The transition coordinator provides information about the translation that is about to start:

/// A Boolean value that indicates whether the user is current dragging the overlay.
var isDragging: Bool { get }

/// The overlay velocity.
var velocity: CGPoint { get }

/// The current translation height.
var overlayTranslationHeight: CGFloat { get }

/// The notch indexes.
var notchIndexes: Range<Int> { get }

/// The reachable indexes. Some indexes might be disabled by the `canReachNotchAt` delegate method.
var reachableIndexes: [Int] { get }

/// Returns the height of the specified notch.
func height(forNotchAt index: Int) -> CGFloat

/// A Boolean value indicating whether the transition is explicitly animated.
var isAnimated: Bool { get }

/// A Boolean value indicating whether the transition was cancelled.
var isCancelled: Bool { get }

/// The overlay height the container expects to reach.
var targetTranslationHeight: CGFloat { get }

and allows you to add animations alongside it:

transitionCoordinator.animate(alongsideTransition: { context in
    // ...
}, completion: nil)

Examples

To test the examples, open OverlayContainer.xcworkspace and run the OverlayContainer_Example target.

Choose the layout you wish to display in the AppDelegate:

  • MapsLikeViewController: A custom layout which adapts its hierachy on rotations.

Maps

  • ShortcutsLikeViewController: A custom layout which adapts its hierachy on trait collection changes: Moving from a UISplitViewController on regular environment to a simple StackViewController on compact environment. Visualize it on an iPad Pro.

Shortcuts

Advanced usage

Multiple overlays

OverlayContainer does not provide a built-in view controller navigation management. It focuses its effort on the overlay translation.

However in the project, there is an example of a basic solution to overlay multiple overlays on top of each other, like in the Apple Maps app. It is based on an UINavigationController and a custom implementation of its delegate:

// MARK: - UINavigationControllerDelegate

func navigationController(_ navigationController: UINavigationController,
                          animationControllerFor operation: UINavigationController.Operation,
                          from fromVC: UIViewController,
                          to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return OverlayNavigationAnimationController(operation: operation)
}

func navigationController(_ navigationController: UINavigationController,
                          didShow viewController: UIViewController,
                          animated: Bool) {
    overlayController.drivingScrollView = (viewController as? SearchViewController)?.tableView
}

OverlayNavigationAnimationController tweaks the native behavior of the UINavigationController: it slides the pushed view controllers up from the bottom of the screen. Feel free to add shadows and modify the animation curve depending on your needs. The only restriction is that you can not push an UINavigationController inside another UINavigationController.

Presenting an overlay container

The translation of an overlay view controller can be coupled with the presentation state of its container. Subclass OverlayContainerPresentationController to be notified any time an overlay translation occurs in the presented content or use the built-in OverlayContainerSheetPresentationController class.

A frequent use case is to reproduce the presentation style of an UIActivityViewController. ActivityControllerPresentationLikeViewController provides a basic implementation of it:

func displayActivityLikeViewController() {
    let container = OverlayContainerViewController()
    container.viewControllers = [MyActivityViewController()]
    container.transitioningDelegate = self
    container.modalPresentationStyle = .custom
    present(container, animated: true, completion: nil)
}

// MARK: - UIViewControllerTransitioningDelegate

func presentationController(forPresented presented: UIViewController,
                            presenting: UIViewController?,
                            source: UIViewController) -> UIPresentationController? {
    return OverlayContainerSheetPresentationController(
        presentedViewController: presented,
        presenting: presenting
    )
}

If the user taps the background content or drags the overlay down fastly, the container controller will be automatically dismissed.

Enabling & disabling notches

OverlayContainer provides a easy way to enable & disable notches on the fly. A frequent use case is to show & hide the overlay. ShowOverlayExampleViewController provides a basic implementation of it:

var showsOverlay = false

func showOrHideOverlay() {
    showsOverlay.toggle()
    let targetNotch: Notch = showsOverlay ? .med : .hidden
    overlayContainerController.moveOverlay(toNotchAt: targetNotch.rawValue, animated: true)
}

// MARK: - OverlayContainerViewControllerDelegate

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    heightForNotchAt index: Int,
                                    availableSpace: CGFloat) -> CGFloat {
    switch Notch.allCases[index] {
    case .max:
        return ...
    case .med:
        return ...
    case .hidden:
        return 0
    }
}

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    canReachNotchAt index: Int,
                                    forOverlay overlayViewController: UIViewController) -> Bool {
    switch Notch.allCases[index] {
    case .max:
        return showsOverlay
    case .med:
        return showsOverlay
    case .hidden:
        return !showsOverlay
    }
}

Make sure to use the rigid overlay style if the content can not be flattened.

Backdrop view

Coordinate the overlay movements to the aspect of a view using the dedicated delegate methods. See the backdrop view example.

backdrop

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    willTranslateOverlay overlayViewController: UIViewController,
                                    transitionCoordinator: OverlayContainerTransitionCoordinator) {
    transitionCoordinator.animate(alongsideTransition: { [weak self] context in
        self?.backdropViewController.view.alpha = context.translationProgress()
    }, completion: nil)
}

Safe Area issues

Be careful when using safe areas. As described in the WWDC "UIKit: Apps for Every Size and Shape" video, the safe area insets will not be updated if your views exceeds the screen bounds. This is specially the case when using the OverlayStyle.expandableHeight: when the overlay exceeds the bottom screen limit, its safe area will not be updated.

The simpliest way to handle the safe area correctly is to compute your notch heights using the safeAreaInsets of the container and avoid the safeAreaLayoutGuide use in your overlay view:

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    heightForNotchAt index: Int,
                                    availableSpace: CGFloat) -> CGFloat {
    let bottomInset = containerViewController.view.safeAreaInsets.bottom
    switch OverlayNotch.allCases[index] {

        // ...

        case .minimum:
            return bottomInset + 100
    }
}

If you depend on UIKit native components that do not ignore the safe area like a UINavigationBar, use the OverlayStyle.flexibleHeight style.

Custom Translation

Adopt OverlayTranslationFunction to modify the relation between the user's finger translation and the actual overlay translation.

By default, the overlay container uses a RubberBandOverlayTranslationFunction that provides a rubber band effect.

rubberBand

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    overlayTranslationFunctionForOverlay overlayViewController: UIViewController) -> OverlayTranslationFunction? {
    let function = RubberBandOverlayTranslationFunction()
    function.factor = 0.7
    function.bouncesAtMinimumHeight = false
    return function
}

Custom Translation Animations

Adopt OverlayTranslationTargetNotchPolicy & OverlayAnimatedTransitioning protocols to define where the overlay should go once the user's touch is released and how to animate the translation.

By default, the overlay container uses a SpringOverlayTranslationAnimationController that mimics the behavior of a spring. The associated target notch policy RushingForwardTargetNotchPolicy will always try to go forward if the user's finger reachs a certain velocity. It might also decide to skip some notches if the user goes too fast.

Tweak the provided implementations or implement our own objects to modify the overlay translation behavior.

animations

func overlayTargetNotchPolicy(for overlayViewController: UIViewController) -> OverlayTranslationTargetNotchPolicy? {
    let policy = RushingForwardTargetNotchPolicy()
    policy.minimumVelocity = 0
    return policy
}

func animationController(for overlayViewController: UIViewController) -> OverlayAnimatedTransitioning? {
    let controller = SpringOverlayTranslationAnimationController()
    controller.damping = 0.2
    return controller
}

Reloading the notches

You can reload all the data that is used to construct the notches using the dedicated method:

func invalidateNotchHeights()

This method does not reload the notch heights immediately. It only clears the current container's state. Because the number of notches may change, the container will use its target notch policy to determine where to go. Call moveOverlay(toNotchAt:animated:) to override this behavior.

Requirements

OverlayContainer is written in Swift 5. Compatible with iOS 10.0+.

Installation

OverlayContainer is available through CocoaPods. To install it, simply add the following line to your Podfile:

Cocoapods

pod 'OverlayContainer'

Carthage

Add the following to your Cartfile:

github "https://github.com/applidium/OverlayContainer"

Swift Package Manager

OverlayContainer can be installed as a Swift Package with Xcode 11 or higher. To install it, add a package using Xcode or a dependency to your Package.swift file:

.package(url: "https://github.com/applidium/OverlayContainer.git", from: "3.4.0")

SwiftUI

See DynamicOverlay

Author

@gaetanzanella, [email protected]

License

OverlayContainer is available under the MIT license. See the LICENSE file for more info.

Comments
  • Bottom of Rigid layout panel moves above bottom of screen when dragging, is there a way to stop this?

    Bottom of Rigid layout panel moves above bottom of screen when dragging, is there a way to stop this?

    Hello, really liking the library so far as it feels more responsive than other libraries and feels like apple’s own floating panel.

    I just have a quick question about the ridged style. Is there a way to stop the bottom of the overlay container from moving higher than the bottom of the screen as the user drags. I’ve tried using the flexible style for my layout but the overlay controller squishes my stack view.

    Pretty much just wanting to know if there’s a way to pin the bottom of the rigid overlay controller to the bottom of the screen.

    opened by Kohdepitcher 12
  • Support for top to bottom overlay

    Support for top to bottom overlay

    Would it be possible to support drag down overlay view with this library. I managed to achieve the desired effect by flipping the transform however as expected the pan gesture would need to be adjusted too

    Do you have plans to support this?

    opened by alexjameslittle 8
  • `reloadNotchHeights()` should be exposed

    `reloadNotchHeights()` should be exposed

    I have a situation where my notch heights are changing, so I found the function OverlayContainerViewControllerConfiguration.reloadNotchHeights() which does the job. Unfortunately the configuration property inside OverlayContainerViewController is private so I can't call it.

    As a quick workaround you could declare configuration as private(set) which allows reading the variable.

    opened by fl034 8
  • Gesture recognizer conflicts with UITableViewCell gesture recognizers for cell actions

    Gesture recognizer conflicts with UITableViewCell gesture recognizers for cell actions

    Describe the bug Gesture recognizer conflicts with UITableViewCell gesture recognizers for cell actions Expected behavior I should reliably be able to swipe on a cell when it is placed in the overlaycontainer.

    I pan gesture property is private so I don't have access to require it to fail to the cell swipe gestures.

    How do I get swipeable tableviewcells to work using OverlayContainer?

    opened by bryan1anderson 7
  • I want to detect when moveOverlay()'s animation done

    I want to detect when moveOverlay()'s animation done

    I want to make OverlayContainerViewController's dismiss animation

    the animation would be like this : when NavigationVC stack's size became to 0, OverlayContainerViewController is going to call moveOverlay() with zero index of notch's height and I want to remove the OverlayViewController when the moveOverlay's animation is done

    But translationController?.moveOverlay hasn't completionHandler should I add a completionHadnler manually? or there is another way to detect when moveOverlay()'s animation is done ?

    opened by msk-psp 7
  • didEndDraggingOverlay is called after a moveOverlay call

    didEndDraggingOverlay is called after a moveOverlay call

    This is not a bug and intentional I'd guess, but what do you think about separating 'dragging' and calling moveOverlay callbacks, e.g something similar to

    func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                            didEndDraggingOverlay overlayViewController: UIViewController,
                                            transitionCoordinator: OverlayContainerTransitionCoordinator) {}
    

    The above would be the original callback but only called when a user actually drags.

    func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                            didEndMovingOverlay overlayViewController: UIViewController,
                                            transitionCoordinator: OverlayContainerTransitionCoordinator) {}
    

    The above would be an additional callback but only called after moveOverlay call has finished?

    Thoughts?

    opened by joustava 6
  • Memory leak

    Memory leak

    Describe the bug A clear and concise description of what the bug is.

    Expected behavior A clear and concise description of what you expected to happen.

    Screenshots, videos or sample codes If applicable, add screenshots to help explain your problem.

    Environnement :

    • Device: iPhoneX
    • OS: iOS 13.6
    • OverlayContainer Version 3.5.0

    Additional context Add any other context about the problem here.

    image

    window?.rootViewController = UINavigationController(rootViewController: TestViewController())
    
    navigationController?.pushViewController(ShowOverlayExampleViewController(), animated: true)
    

    ShowOverlayExampleViewController popViewController deinit does not execute

    image

    opened by fanglinwei 5
  • Duration of animation for moveOverlay

    Duration of animation for moveOverlay

    This is more of a request for help than an issue, I guess, but I can't figure out how to set the duration of the animation when calling moveOverlay(toNotchAt:,animated:). I even considered importing the entire OverlayContainer as classes instead of a pod so I could manipulate it if it was private, but I can't find a duration anywhere, just velocity and advanced animation protocols. It would be nice to make it animate alongside another animation too, but I just don't understand how. The ShowOverlayExample just uses the basic "moveOverlay" with the default duration, so it couldn't help me..

    opened by sfla 5
  • Subclass OverlayContainerViewController?

    Subclass OverlayContainerViewController?

    Currently it is not possible to subclass OverlayContainerViewController, afaik. Xcode error message: "Cannot inherit from non-open class 'OverlayContainerViewController' outside of its defining module" This is probably due to OverlayContainerViewController being "public" and not "open". Open exists since Swift 3 and allows a class or function to be subclassed or overridden outside the current module. It would be great if we could subclass OverlayContainerViewController for custom contained overlays.

    opened by gorkemg 5
  • Gestures conflict with an overlay's inner scroll view

    Gestures conflict with an overlay's inner scroll view

    Using the overlay with the .expandableHeight style, I came across a scenario where I would not want to use the overlay's inner scroll view as driving for the overlay. That is for two reasons:

    • when in collapsed state, it should not be possible to scroll the content of the overlay's inner scroll view, and hence it cannot drive when disabled
    • even when enabled, but at the same time representing some kind of empty state (contentSize.height < bounds.height), it seems to be not possible to drag the overlay because there is nothing to actually scroll in the driving scroll view

    If I skip setting the drivingScrollView (or implementing the appropriate delegate method) however, the overlay's own pan gesture gets ignored whenever the inner scroll view is enabled. As a result, it becomes not possible to e.g. collapse the expanded overlay.

    After exploring the code a bit and with some experiments, I found that the problem can be resolved by allowing the overlay's private pan gesture to be recognized simultaneously with the pan gesture of the inner scroll view on certain condition. In particular, by allowing recognition when the inner scroll view reaches the top of its content, like this:

    // PanGestureOverlayTranslationDriver.swift
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            if panGestureRecognizer.drivingScrollView == nil,
               gestureRecognizer is OverlayTranslationGestureRecognizer,
               otherGestureRecognizer is UIPanGestureRecognizer,
               let scrollView = otherGestureRecognizer.view as? UIScrollView  {
                return scrollView.contentOffset.y <= 0
            }
            return false
        }
    

    @gaetanzanella do you think adding the above change makes sense? or does that break the library's intent somehow? 🤔 please let me know and I can make a PR out of it, or otherwise just fork 🙂

    opened by pavelhiq 4
  • `OverlayContainerSheetPresentationController` doesn't update view frame when device is rotated

    `OverlayContainerSheetPresentationController` doesn't update view frame when device is rotated

    Describe the bug OverlayContainerSheetPresentationController doesn't respect device orientation changes and doesn't update the presented view controller's view

    Expected behavior OverlayContainerSheetPresentationController will update its content view within the device rotation animation

    Screenshots, videos or sample codes video demo.mp4.zip

    Screen Shot 2020-05-27 at 6 10 16 PM

    Environnement :

    • Device: iPad mini 4
    • OS: iOS 13.3
    • OverlayContainer Version: 3.5.0-beta.2
    opened by GRiMe2D 4
  • Manage multiple driving scrollviews

    Manage multiple driving scrollviews

    OverlayContainer could easily manage multiple driving scroll views:

    containerViewController.drivingScrollViews = ...
    
    func overlayContainerViewController(_ containerViewController: OverlayContainerViewController, scrollViewsDrivingOverlay overlayViewController: UIViewController) -> [UIScrollView] {
        return ...
    }
    
    enhancement 
    opened by gaetanzanella 0
  • Page sheet dismiss gesture conflict with driving scroll view

    Page sheet dismiss gesture conflict with driving scroll view

    When scrolling down any scroll view in the overlay in view controllers presented using page sheet modal presentation style, the view controller is interactively dismissed.

    Page sheet should not be dismissed when scrolling the driving scroll view down. But it could be enabled for other other areas outside the overlay controller.

    opened by aabdellah 3
  • Animation jumps when touching overlay during animation (BackdropExampleViewController)

    Animation jumps when touching overlay during animation (BackdropExampleViewController)

    Hi, I'm trying to animate other views in sync with the overlay transition. The BackdropExampleViewController example comes very close to what I want to do.

    Everything works fine, but when I slide up the overlay, and then quickly slide it down again (before the slide-up animation has completed), the background transparency "jumps" a bit.

    I've attached a video. It looks subtle here, but it becomes more annoying in my actual application. Do you have an idea how to fix this?

    Best, Johannes animation.mov.zip

    opened by johannesd 4
Releases(3.5.2)
  • 3.5.2(Nov 7, 2021)

  • 3.5.1(Aug 22, 2020)

  • 3.5.0(Aug 7, 2020)

    Added

    • OverlayContainerPresentationController: An abstract class that can be used to manage the transition animations and the presentation of overlay containers onscreen.
    • OverlayContainerSheetPresentationController: An OverlayContainerPresentationController subclass that adds a dimming layer over the background content and a drag-to-dismiss & tap-to-dismiss gestures.

    Updated

    • The overlay container view autorizing mask is now [.flexibleHeight, .flexibleWidth]
    Source code(tar.gz)
    Source code(zip)
  • 3.5.0-beta.2(Apr 23, 2020)

    • Renaming DefaultOverlayContainerSheetDismissalPolicy > ThresholdOverlayContainerSheetDismissalPolicy
    • Add properties to OverlayContainerTransitionContext
    • Improve overlay context hierarchy
    Source code(tar.gz)
    Source code(zip)
  • 3.5.0-beta.1(Apr 10, 2020)

    Added

    • OverlayContainerPresentationController: An abstract class that can be used to manage the transition animations and the presentation of overlay containers onscreen.
    • OverlayContainerSheetPresentationController: An OverlayContainerPresentationController subclass that adds a dimming layer over the background content and a drag-to-dismiss & tap-to-dismiss gestures.
    Source code(tar.gz)
    Source code(zip)
  • 3.4.1(Apr 6, 2020)

  • 3.4.0(Mar 30, 2020)

  • 3.3.1(Mar 23, 2020)

  • 3.3.0(Mar 9, 2020)

  • 3.2.1(Jan 10, 2020)

  • 3.2.0(Jan 10, 2020)

  • 3.1.0(Jan 10, 2020)

  • 3.0.0(Jan 10, 2020)

    • All the translations are now deferred to the next layout pass. The translations can now be scheduled right after the initialization of the container. Furthermore the layout will not break if the container moves the overlay or invalidates its notch heights in response to a size change.
    • SpringOverlayTranslationAnimationController almost nullifies its damping value when the container has a rigid style to avoid the panel to be lifted above the bottom of the screen when an animated transition occurs.
    • New overlay style expandableHeight
    • New delegate tracking API: willTranslateOverlay, didMoveOverlay, willMoveOverlay, willEndDraggingOverlay, willStartDraggingOverlay
    • invalidateNotchHeight uses the target notch policy to determine where to go by default
    Source code(tar.gz)
    Source code(zip)
  • 2.0.2(Jan 10, 2020)

  • 2.0.0(Jan 10, 2020)

    • Add canReachNotchAt delegate's method to disable or enable notches on the fly
    • OverlayContainerViewController now uses the last view controller of its viewControllers property 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.
    • Handle a new edge case: the overlay container has only one notch
    Source code(tar.gz)
    Source code(zip)
  • 1.3.0(Jan 10, 2020)

  • 1.2.0(Jan 10, 2020)

  • 1.1.2(Jan 10, 2020)

  • 1.1.0(Jan 10, 2020)

  • 1.0.4(Jan 10, 2020)

  • 1.0.3(Jan 10, 2020)

  • 1.0.2(Jan 10, 2020)

  • 1.0.1(Jan 10, 2020)

  • 1.0.0(Jan 10, 2020)

Full configurable spreadsheet view user interfaces for iOS applications. With this framework, you can easily create complex layouts like schedule, gantt chart or timetable as if you are using Excel.

kishikawakatsumi/SpreadsheetView has moved! It is being actively maintained at bannzai/SpreadsheetView. This fork was created when the project was mov

Kishikawa Katsumi 34 Sep 26, 2022
CITreeView created to implement and maintain that wanted TreeView structures for IOS platforms easy way

CITreeView CITreeView created to implement and maintain that wanted TreeView structures for IOS platforms easy way. CITreeView provides endless treevi

Cenk Işık 126 May 28, 2022
Windless makes it easy to implement invisible layout loading view.

Windless Windless makes it easy to implement invisible layout loading view. Contents Requirements Installation Usage Looks Credits Communication Licen

ArLupin 940 Dec 22, 2022
Swift based simple information view with pointed arrow.

InfoView View to show small text information blocks with arrow pointed to another view.In most cases it will be a button that was pressed. Example To

Anatoliy Voropay 60 Feb 4, 2022
Placeholder views based on content, loading, error or empty states

StatefulViewController A protocol to enable UIViewControllers or UIViews to present placeholder views based on content, loading, error or empty states

Alexander Schuch 2.1k Dec 8, 2022
Swift Package for distributing Mozilla's Rust-based application components

Swift Package for Mozilla's Rust Components This repository is a Swift Package for distributing releases of Mozilla's various Rust-based application c

Mozilla 19 Dec 30, 2022
A simple Elm-like Store for SwiftUI, based on ObservableObject

ObservableStore A simple Elm-like Store for SwiftUI, based on ObservableObject.

Gordon Brander 28 Nov 8, 2022
BulletinBoard is an iOS library that generates and manages contextual cards displayed at the bottom of the screen

BulletinBoard is an iOS library that generates and manages contextual cards displayed at the bottom of the screen. It is especially well

Alexis (Aubry) Akers 5.3k Jan 2, 2023
A library to recreate the iOS Apple Music now playing transition

DeckTransition DeckTransition is an attempt to recreate the card-like transition found in the iOS 10 Apple Music and iMessage apps. Hereʼs a GIF showi

Harshil Shah 2.2k Dec 15, 2022
⚡️ A library of widgets and helpers to build instant-search applications on iOS.

By Algolia. InstantSearch family: InstantSearch iOS | InstantSearch Android | React InstantSearch | InstantSearch.js | Angular InstantSearch | Vue Ins

Algolia 567 Dec 20, 2022
An iOS Library that makes shadows management easy on UIView.

ShadowView is an iOS Shadow library that makes view's shadow implementation easy and sweet ?? ?? . Add simple shadows to add a gaussian blurred projec

Pierre 404 Dec 8, 2022
StarryStars is iOS GUI library for displaying and editing ratings

StarryStars StarryStars is iOS GUI library for displaying and editing ratings Features StarryStars' RatingView is both IBDesignable and IBInspectable

Peter Prokop 175 Nov 19, 2022
A library to imitate the iOS 10 Maps UI.

Pulley A library to imitate the drawer in Maps for iOS 10/11. The master branch follows the latest currently released version of Swift. If you need an

52inc 2k Dec 29, 2022
A nice iOS View Capture Swift Library which can capture all content.

SwViewCapture A nice iOS View Capture Library which can capture all content. SwViewCapture could convert all content of UIWebView to a UIImage. 一个用起来还

Xing Chen 597 Nov 22, 2022
User Interface Library for iOS

Why Sejima Because in modern mobile applications, you often reuse user interface components. To avoid code duplication, we have tried to provide you w

Move Upwards 64 Dec 22, 2022
A minimalistic looking banner library for iOS. It supports multiple customizable kinds of Banner types

A minimalistic looking banner library for iOS. It supports multiple customizable kinds of Banner types

Emre Armagan 12 Oct 10, 2022
:octocat:💧 A slider widget with a popup bubble displaying the precise value selected. Swift UI library made by @Ramotion

FLUID SLIDER A slider widget with a popup bubble displaying the precise value selected written on Swift. We specialize in the designing and coding of

Ramotion 1.9k Dec 23, 2022
A library, which adds the ability to hide navigation bar when view controller is pushed via hidesNavigationBarWhenPushed flag

HidesNavigationBarWhenPushed A library, which adds the ability to hide navigation bar when view controller is pushed via hidesNavigationBarWhenPushed

Danil Gontovnik 55 Oct 19, 2022
A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles

A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles while pushing or popping a view controller for all orientations. And you don't need to write any line of code for it, it all happens automatically.

Zhouqi Mo 3.3k Dec 21, 2022