A framework for presenting bars and view controllers as popup, much like the look and feel of Apple Music App.

Overview

PBPopupController

Build Status Carthage compatible Version SwiftPM compatible Mac Catalyst compatible License Platform Swift Version

PBPopupController is a framework for presenting bars and view controllers as popup, much like the look and feel of Apple Music App.

Image

Overview

PBPopupController allows to configure a popup bar (like the mini player of Apple Music App), dock it to the bottom bar of a presenting view container controller (like UITabBarController, UINavigationController). The presenting view controller can be any UIViewController subclass.

Each view controller can present a popup bar, docked to a bottom view. For UITabBarController subclasses, the default is the tab bar. For UINavigationController subclasses, the default view is the toolbar. For other classes, the popup bar is presented at the bottom of the screen. View controller subclasses can provide their own bottom bar views.

Once the popup bar is configured (see the properties in the PBPopupBar class) with a style, an image, a title, a sub-title, buttons, effects and colors, you present it with the above view controller providing a required popup content view controller (like the maxi player of Apple Music App).

Once the popup bar is presented with a popup content view controller, the user can swipe or tap the popup bar at any point to present the content view controller. After finishing, the user dismisses this view controller by either swiping or tapping the popup close button porvided by the system.   Popup close buttons styles are labeled chevron for modern style chevron close button and round for iOS 9-style close buttons.

You can also present and dismiss the popup content view controller programmatically.

The popup bar has a prominent style based on the modern Music app look and feel and below and a compact style for iOS 9-style look and feel.. You can change these default values.

The presentation options provided by the framework are listed in the PBPopupPresentationStyle enumeration. They make the presentation look like the behavior of the Apple Music App. For iOS 9, the presentation style was fullScreen by default and for iOS 10 and below, the style was deck. The default is deck. You can change these default values. The custom option allows you to present the controller on a part of the screen.

Installation

Swift Package Manager

PBPopupController supports SPM versions 5.1.0 and above. To use SPM, you should use Xcode 11 or above to open your project. Click File -> Swift Packages -> Add Package Dependency, enter https://github.com/iDevelopper/PBPopupController. Select the version you’d like to use.

Carthage

Add the following to your Cartfile:

github "iDevelopper/PBPopupController"

Make sure you follow the Carthage integration instructions here.

Manual

Drag the PBPopupController.xcodeproj project to your project, and add PBPopupController.framework to Embedded Binaries in your project target's General tab. Xcode should sort everything else on its own.

CocoaPods

PBPopupController is available for installation using the Cocoa dependency manager CocoaPods.

Add the following to your project's Podfile:

pod 'PBPopupController'

Requirements

  • iOS 11 or later.
  • ARC memory management.

Features

  • Category methods on UIViewController.
  • Handling of rotations.
  • Plays nicely with any child view controllers or parent controllers.
  • Seamless integration of tap and pan gesture recognizers.
  • Delegate methods for getting full state of the controller and implementing your own code hooks for customizing behavior.
  • Data source methods for asking custom popup bar' labels.
  • Full Right-To-Left support.
  • Accessibility support.
  • iOS 13 dark mode support.
  • macOS Catalyst support.
  • iPad look and feel support.

Basic API Description

  • Configuring and presenting a popup bar:
        self.tabBarController?.popupController.delegate = self
        
        if let popupBar = self.tabBarController?.popupBar {

            popupBar.dataSource = self
            
            popupBar.image = UIImage(named: "Cover01")
            popupBar.title = "Title"
            popupBar.subtitle = " A subtitle"
            popupBar.accessibilityLabel = "My custom label"
            
            let popupPlayButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "play-small"), style: .plain, target: self, action: #selector(playPauseAction(_:)))
            popupPlayButtonItem.accessibilityLabel = NSLocalizedString("Play", comment: "")
            let popupNextButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "next-small"), style: .plain, target: self, action: #selector(nextAction(_:)))
            popupNextButtonItem.accessibilityLabel = NSLocalizedString("Next track", comment: "")
            
            popupBar.rightBarButtonItems = [popupPlayButtonItem, popupNextButtonItem]
            
            let popupContentVC = self.storyboard?.instantiateViewController(withIdentifier: "PopupContentViewController") as? PopupContentViewController
            
            self.tabBarController?.presentPopupBar(withPopupContentViewController: popupContentVC, animated: true, completion: {
                print("Presented")
            })
        }
  • Opening a popup content view controller programmatically:
        self.tabBarController?.openPopup(animated: true, completion: {
            print("Open")
        })
  • Closing a popup content view controller programmatically:
        self.tabBarController?.closePopup(animated: true, completion: {
            print("Closed")
        })
  • Delegate methods for getting state of the controller:
    func popupController(_ popupController: PBPopupController, stateChanged state: PBPopupPresentationState, previousState: PBPopupPresentationState) {
        PBLog("stateChanged state: \(state.description) - previousState: \(previousState.description)")
    }
    func popupController(_ popupController: PBPopupController, didOpen popupContentViewController: UIViewController) {
        PBLog("didOpen - state: \(popupController.popupPresentationState.description)")
    }

etc...

  • PBPopupBar dataSource methods for providing label instances (such as MarqueeLabel):
    lazy var label: MarqueeLabel = {
        let marqueeLabel = MarqueeLabel(frame: .zero, rate: 15, fadeLength: 10)
        marqueeLabel.leadingBuffer = 0.0
        marqueeLabel.trailingBuffer = 5.0
        marqueeLabel.animationDelay = 1.0
        marqueeLabel.type = .continuous
        return marqueeLabel
    }()

...

    func titleLabel(for popupBar: PBPopupBar) -> UILabel? {
        return self.label
    }
    func subtitleLabel(for popupBar: PBPopupBar) -> UILabel? {
        return self.sublabel
    }

Managing the status bar

Since iOSS 13, the status bar is not animated correctly by Apple. So, you can set the properties:

popupPreferredStatusBarStyle for the preferred status bar style of the popup content view controller, containerPreferredStatusBarStyle for preferred status bar style of the container view controller.

When you override the preferredStatusBarStyle variable in your popup content view controller, return container.popupController.popupStatusBarStyle:

    override public var preferredStatusBarStyle: UIStatusBarStyle {
        guard let containerVC = self.popupContainerViewController else {return.default}
        guard let popupContentView = containerVC.popupContentView else {return .default}
    
        if popupContentView.popupPresentationStyle != .deck {
            return .default
        }
        return containerVC.popupController.popupStatusBarStyle
    }

API Documentation

You can find the docs here. Documentation is generated with jazzy and hosted on GitHub-Pages.

Special Mention

A Special Thank to Leo Natan.

This code was inspired on his excellent framework LNPopupController.

Author

Patrick BODET aka iDevelopper

License

PBPopupController is available under the MIT license, see the LICENSE file for more information.

Please tell me when you use this controller in your project!

Regards,

Patrick Bodet aka iDevelopper

Comments
  • Incorrect tab bar height when user partially swipes up miniplayerview, let's go, and then changes orientation

    Incorrect tab bar height when user partially swipes up miniplayerview, let's go, and then changes orientation

    I'm noticing that if a user were to slightly pull up the miniplayer, let go, and then change orientation from portrait to landscape mode, the tab bar is incorrect.

    This becomes much more obvious when the user pull the minibar from the bottom, it reaches an open state, user changes orientation, and then user pulls the playerview down so it becomes a miniplayer again.

    Changing orientation back and forth twice seems to bring everything back to normal but it would be nice for users to not have to do that for it to work.

    I've been looking inside PBPopupInteractivePresentationController.swift to see if the source of this bug is here, but to no avail. Is there a place you can suggest I take a look? I don't want to just dump this issue on you; I can certainly help :)

    opened by aguzmanballen 17
  • Popup  layout is skewed.

    Popup layout is skewed.

    Thank you for amazing library. It's been pretty helpful for me!!

    But when I get back app after background, the layout is skewed like a Photo. IMG_4289

    I’m using a code as specified in the documentation like below Do I need to write anything else? Thanks!

    self.tabBarController?.popupController.delegate = self

        if let popupBar = self.tabBarController?.popupBar {
    
            popupBar.dataSource = self
            
            popupBar.image = UIImage(named: "Cover01")
            popupBar.title = "Title"
            popupBar.subtitle = " A subtitle"
            popupBar.accessibilityLabel = "My custom label"
            
            let popupPlayButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "play-small"), style: .plain, target: self, action: #selector(playPauseAction(_:)))
            popupPlayButtonItem.accessibilityLabel = NSLocalizedString("Play", comment: "")
            let popupNextButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "next-small"), style: .plain, target: self, action: #selector(nextAction(_:)))
            popupNextButtonItem.accessibilityLabel = NSLocalizedString("Next track", comment: "")
            
            popupBar.rightBarButtonItems = [popupPlayButtonItem, popupNextButtonItem]
            
            let popupContentVC = self.storyboard?.instantiateViewController(withIdentifier: "PopupContentViewController") as? PopupContentViewController
            
            self.tabBarController?.presentPopupBar(withPopupContentViewController: popupContentVC, animated: true, completion: {
                print("Presented")
            })
        }
    

    .

    opened by YugoMatsuda 14
  • Buttons in the PopupBar do not respond when navigating back

    Buttons in the PopupBar do not respond when navigating back

    When using the PBPopupControllerSample app, I encountered one navigation issue.

 On MainTableViewController I click on a cell in the table "NavigationController"

    When I move forward a few ViewControllers by clicking on the "Next" cell (pushNext) and clicking on the song cell (presentPopupBar), the PBPopupBar appears.

    On this ViewController where the presentPopupBar was executed, I can interact with the playPauseAction and nextAction buttons that are located on the called PBPopupBar.

    But if I navigate back a few ViewControllers in navigation, then the playPauseAction and nextAction buttons in the PBPopupBar won't call their respective methods.

    If, however, if I move forward several ViewControllers (pushNext), I can interact with the playPauseAction and nextAction buttons and call the methods

    Can you please tell me why this might happen?

    opened by balabon7 6
  • Memory Leak

    Memory Leak

    Greetings, thanks again for your work. I noticed a strange ARC behavior, after I used TabBarController with PopupBar, I make another Root controller, I have a TabBarController with all the controllers in my memory

    Problems to be found in

    presentPopupBar(withPopupContentViewController: demoViewController, animated: true, completion: nil)

    What do you advise? I am currently working on a solution

    opened by Terens777 6
  • No visual effect of Modal Page Sheet

    No visual effect of Modal Page Sheet

    Hello Patrick. I implemented a project (PGPopupSample) using PBPopupController.

    But when I call func presentPopupBar() and present the PopupContentViewController, then the controller below it was not animated as a stack. (There's just an influx one on one)

    PBPopupSample

    And here is how it looks in your PBPopupControllerSample application:

    PBPopupControllerSample

    I tried changing popupContentView.popupPresentationStyle but it didn't change anything in my case.

    What do you think could be the reason?

    Below I have provided a simple project that reproduces this issue:

    https://github.com/balabon7/PBPopupSample

    opened by balabon7 3
  • How to dismiss popup with my own custom button action

    How to dismiss popup with my own custom button action

    I tried with self.popupContentViewController.closePopup(animated: true)but it always comes nil, I have used the same way how it was described in PBPopupLeakTest.zip file project u have shared on https://github.com/iDevelopper/PBPopupController/issues/3

    opened by dev-abdul02 2
  • It is not possible to use a custom controller

    It is not possible to use a custom controller

      func presentCustomPopup() {
            if let containerVC = self.containerController {
                let customYTBar = self.storyboard?.instantiateViewController(withIdentifier: "CustomPopupBarViewController") as! CustomPopupBarViewController
                customYTBar.view.backgroundColor = .clear
                containerVC.popupController.dataSource = self
                containerVC.popupBar.isTranslucent = false
                containerVC.popupBar.inheritsVisualStyleFromBottomBar = false
                containerVC.popupBar.customPopupBarViewController = customYTBar
                containerVC.popupContentView.popupCloseButtonStyle = .round
                containerVC.popupContentView.popupEffectView.effect = nil
                let popupContentController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PopupContentViewController") as! PopupContentViewController
                containerVC.popupBar.image = customYTBar.imageView.image
                containerVC.popupBar.title = customYTBar.titleLabel.text
                containerVC.popupBar.subtitle = customYTBar.subtitleLabel.text
                DispatchQueue.main.async {
                    containerVC.presentPopupBar(withPopupContentViewController: popupContentController, animated: true) {
                        PBLog("Custom Popup Bar Presented")
                    }
                }
            }
        }
    

    after called this in DemoChildViewController in you Test project, crashed app

    Log: *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x600001a66840 "PBPopupController.PBPopupBar:0x7fec54a7afe0.top"> and <NSLayoutYAxisAnchor:0x600001a67040 "UIView:0x7fec54a785e0.top"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'

    opened by Terens777 2
  • Scroll view gesture conflicts

    Scroll view gesture conflicts

    If add any scrollable controller as popup(table view, scroll view) gestures will conflict. I have troubles with adding UISlider to cell of table view. The solution is to activate dismissing popup swipe down gesture wile scroll view scrolled to the very top.

    opened by salminalex 2
  • Mysterious black bar appears over SwiftUI subviews.

    Mysterious black bar appears over SwiftUI subviews.

    Hello!

    I have an app with 4 ViewControllers in a UITabbar. ViewController 1 is a regular UIKit view. No problems. The remaining ViewControllers contain SwiftUI views (making use of UIHostingController) and whenever those views come into focus, a black bar appears and grows larger with each successive appearance of that view. I tried different types of PBPopup bar / controller combinations but no luck. The black bar does not appear in the view heirerarchy debugger. Additionally this issue does not occur if you go through and view all the SwiftUI tabs. It only happens when the PBPopupController has been instantiated before the SwiftUI views. Any insight into this or help would be greatly appreciated. I've attached some images to aid in the description.

    view 1: image

    first appearance (the black bar appears). image

    end result (different tab with the same problem): image

    Best Regards, Samir

    opened by samirsd 1
  • access custom docking viewcontroller property. (help wanted)

    access custom docking viewcontroller property. (help wanted)

    opened by ghimireprashant 1
Owner
Patrick
Patrick
A Swift Popup Module help you popup your custom view easily

JFPopup JFPopup is a Swift Module help you popup your custom view easily. Support 3 way to popup, Drawer, Dialog and BottomSheet. Example To run the e

逸风 77 Dec 14, 2022
⛩ Presenting custom views as a popup in iOS.

FFPopup is a lightweight library for presenting custom views as a popup. Bounce from Top & Bounce to Bottom Bounce from Top & Bounce to Top Bounce in

JonyFang 828 Jan 5, 2023
SSToastMessage is written purely in SwiftUI. It will add toast, alert, and floating message view over the top of any view. It is intended to be simple, lightweight, and easy to use. It will be a popup with a single line of code.

SSToastMessage SSToastMessage is written in SwiftUI. It will add toast, alert, and floating message view over the top of any view. It is intended to b

Simform Solutions 223 Dec 2, 2022
STPopup provides STPopupController, which works just like UINavigationController in popup style, for both iPhone and iPad. It's written in Objective-C and compatible with Swift.

STPopup STPopup provides STPopupController, which works just like UINavigationController in popup style, for both iPhone and iPad. It's written in Obj

Kevin Lin 2.6k Jan 6, 2023
PopupController is a controller for showing temporary popup view.

PopupController PopupController is a controller for showing temporary popup view. Demo Try PopupController on Appetize.io Installation CocoaPods pod '

daisuke sato 338 Dec 14, 2022
A lightweight library for popup view

SHPopup SHPop is lightweight library used for popup view Sample One Sample Two Sample Three Features SHPopup supports a popup inside another popup wit

Shezad Ahamed 37 Oct 2, 2022
UIViewController drop in replacement with much more customisation

PopupViewController UIAlertController drop in replacement with much more customization You can literally replace UIAlertController by PopupViewControl

Thomas Ricouard 21 Jun 27, 2022
Simple way to present custom views as a popup in iOS and tvOS.

PopupKit PopupKit is a simple and flexible iOS framework for presenting any custom view as a popup. It includes a variety of options for controlling h

Pointwelve 59 Mar 1, 2022
Simple Swift class for iOS that shows nice popup windows with animation.

NMPopUpView Simple class for iOS that shows nice popup windows, written in Swift. The project is build with Swift 4.0, so you need Xcode 9.0 or higher

Nikos Maounis 194 Jun 5, 2022
A simple, customizable popup dialog for iOS written in Swift. Replaces UIAlertController alert style.

Introduction Popup Dialog is a simple, customizable popup dialog written in Swift. Features Easy to use API with hardly any boilerplate code Convenien

Orderella Ltd. 3.8k Dec 20, 2022
PopupWindow is a simple Popup using another UIWindow in Swift

PopupWindow PopupWindow is a simple Popup using another UIWindow Feature PopupWindow can be displayed at the top or bottom of the screen. Popup can se

shinji hayashi 415 Dec 5, 2022
The library allows to create simple popup menus

react-native-popup-menu This library allows to create simple popup menus Installation "react-native-popup-menu": "sergeymild/react-native-popup-menu"

SergeyMild 0 Aug 20, 2022
WKWebView handling popup windows

WKWebViewWithPopUp WKWebView handling pop-up windows Property If there is a pop-up window, use the pop-up window. If there is no pop-up window, use th

Hankyeol Park 7 Nov 23, 2022
IAMPopup is a simple class for expressing custom popup in various forms.

IAMPopup Introduction IAMPopup is a simple class for expressing custom popup in various forms. This includes where to display the popup and space to d

Hosung Kang 18 Dec 29, 2022
Subscription View Controller like the Tinder uses

SubscriptionPrompt SubscriptionPrompt is a UIViewController with a carousel at the top and a number of rows at the bottom. Written in Swift, works for

Binur Konarbai 235 Nov 17, 2022
Popover is a balloon library like Facebook app. It is written in pure swift.

Popover Description and appetize.io`s DEMO Usage To run the example project, clone the repo, and run pod install from the Example directory first. Sim

Yusuke Takahashi 2k Jan 2, 2023
Pop-up based view(e.g. alert sheet), can be easily customized.

MMPopupView 中文介绍 A basic Pop-Up Kit allows you to easily create Pop-Up view. You can focus on the only view you want to show. Besides, it comes with 2

ralph li 2.1k Jan 3, 2023
Toasts and popups library written with SwiftUI

Popup View Toasts and popups library written with SwiftUI We are a development agency building phenomenal apps. Usage Put all your body code into a ZS

Exyte 1.9k Jan 6, 2023
LNPopupController is a framework for presenting view controllers as popups of other view controllers, much like the Apple Music and Podcasts apps.

LNPopupController LNPopupController is a framework for presenting view controllers as popups of other view controllers, much like the Apple Music and

Leo Natan 2.9k Jan 2, 2023
PJAlertView - This library is to make your own custom alert views to match your apps look and feel

PJAlertView - This library is to make your own custom alert views to match your apps look and feel

prajeet 6 Nov 10, 2017