PBPopupController

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

PBPopupController 是一个框架,用于将栏和视图控制器呈现为弹出窗口,非常类似于 Apple Music App 的外观和感觉。

Image

概述

PBPopupController 允许配置一个弹出栏(就像 Apple Music App 的迷你播放器),将其停靠到呈现视图容器控制器(如 UITabBarController、UINavigationController)的底部栏。 呈现视图控制器可以是任何 UIViewController 子类。

每个视图控制器都可以呈现一个弹出栏,停靠到底部视图。 对于 UITabBarController 子类,默认是标签栏。 对于 UINavigationController 子类,默认视图是工具栏。 对于其他类,弹出栏会呈现在屏幕底部。 视图控制器子类可以提供它们自己的底部栏视图。

一旦弹出栏配置好(参见 PBPopupBar 类中的属性),包括样式、图像、标题、副标题、按钮、效果和颜色,您可以使用上述视图控制器来呈现它,并提供一个必需的弹出内容视图控制器(就像 Apple Music App 的 Maxi 播放器)。

一旦通过弹出内容视图控制器呈现了弹出栏,用户可以随时滑动或点击弹出栏来呈现内容视图控制器。 完成后,用户可以通过滑动或点击系统提供的弹出关闭按钮来关闭此视图控制器。 弹出关闭按钮样式标记为 chevron 表示现代风格的chevron关闭按钮,round 表示 iOS 9 风格的关闭按钮。

您还可以通过编程方式呈现和关闭弹出内容视图控制器。

弹出栏具有基于现代音乐应用程序外观和感觉的 prominent 样式,以及用于 iOS 9 风格外观和感觉的 compact 样式。您可以更改这些默认值。 对于每一个,都有一个浮动参数用于匹配样式,就像 iOS 17 之后的 Apple 音乐应用程序一样。

您还可以呈现完全自定义的弹出栏。

该框架提供的呈现选项在 PBPopupPresentationStyle 枚举中列出。 它们使呈现看起来像 Apple Music App 的行为。 对于 iOS 9,呈现样式默认为 fullScreen,对于 iOS 10 及更低版本,样式为 deck。 默认值为 deck。您可以更改这些默认值。 custom 选项允许您在屏幕的一部分上呈现控制器。

安装

Swift Package Manager

PBPopupController 支持 SPM 5.1.0 及以上版本。 要使用 SPM,您应该使用 Xcode 11 或更高版本打开您的项目。 单击 File -> Swift Packages -> Add Package Dependency,输入 https://github.com/iDevelopper/PBPopupController。 选择您想使用的版本。

Carthage

将以下内容添加到您的 Cartfile

github "iDevelopper/PBPopupController"

请确保您遵循 Carthage 集成说明 这里.

手动

PBPopupController.xcodeproj 项目拖到您的项目中,并将 PBPopupController.framework 添加到您的项目目标的 General 选项卡中的 Embedded Binaries。 Xcode 应该会自动处理其他所有事情。

CocoaPods

可以使用 Cocoa 依赖项管理器 CocoaPods 安装 PBPopupController

将以下内容添加到您的项目的 Podfile

pod 'PBPopupController'

要求

特性

基本 API 描述

        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")
            })
        }
        self.tabBarController?.openPopup(animated: true, completion: {
            print("Open")
        })
        self.tabBarController?.closePopup(animated: true, completion: {
            print("Closed")
        })
    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)")
    }

等等...

    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
    }

管理状态栏

自 iOS 13 以来,Apple 未正确动画状态栏。 因此,您可以设置属性

popupPreferredStatusBarStyle 用于弹出内容视图控制器的首选状态栏样式,containerPreferredStatusBarStyle 用于容器视图控制器的首选状态栏样式。

当您覆盖弹出内容视图控制器中的 preferredStatusBarStyle 变量时,返回 container.popupController.popupStatusBarStyle

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

API 文档

您可以在此处找到文档。 文档使用 jazzy 生成,并托管在 GitHub-Pages 上。

鸣谢

该框架使用

演示项目使用

特别鸣谢

特别感谢 Leo Natan

此代码的灵感来自他出色的框架 LNPopupController

作者

Patrick BODET aka iDevelopper

许可证

PBPopupController 在 MIT 许可下可用,请参阅 LICENSE 文件获取更多信息。

请告诉我您何时在您的项目中使用此控制器!

此致,

Patrick Bodet aka iDevelopper