You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Storyboard添加全局底部播放视图(排除详情ViewController)

实现全局底部播放栏(Storyboard + ViewController 方案)

我刚好做过类似的需求,用Storyboard设计播放栏再结合自定义导航控制器,就能完美实现全局显示+排除特定页面的效果,具体步骤如下:

1. 创建播放栏专用 ViewController 并在 Storyboard 布局

  • 新建 NowPlayingBarViewController 继承自 UIViewController
  • 打开 Storyboard(可以用Main.storyboard或者单独新建一个),拖入一个ViewController,设置其Class为NowPlayingBarViewController
  • 在Size Inspector里把这个VC的Size改成Freeform,调整高度到60pt左右(和苹果音乐播放栏高度匹配),宽度设为屏幕宽度
  • 设计UI:添加专辑封面ImageView、歌曲名Label、歌手Label、播放暂停按钮等,调整布局和样式(比如半透明背景、圆角)
  • 给这个VC设置Storyboard ID(比如NowPlayingBarVC),方便后续代码初始化

2. 自定义导航控制器承载播放栏

要实现全局显示且排除特定页面,用自定义导航控制器管理是最灵活的方案:

  • 新建 CustomNavigationController 继承自 UINavigationController
  • 在这个类里初始化播放栏VC并添加为子VC,同时监听导航栈变化来控制显示隐藏:
import UIKit

class CustomNavigationController: UINavigationController {
    private var nowPlayingBarVC: NowPlayingBarViewController?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupNowPlayingBar()
        // 设置代理监听页面切换
        delegate = self
    }
    
    private func setupNowPlayingBar() {
        // 从Storyboard初始化播放栏VC
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        guard let barVC = storyboard.instantiateViewController(withIdentifier: "NowPlayingBarVC") as? NowPlayingBarViewController else {
            return
        }
        
        nowPlayingBarVC = barVC
        // 添加为子VC并布局到底部
        addChild(barVC)
        view.addSubview(barVC.view)
        barVC.didMove(toParent: self)
        
        // Auto Layout 约束
        barVC.view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            barVC.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            barVC.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            barVC.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            barVC.view.heightAnchor.constraint(equalToConstant: 60)
        ])
    }
}

// 监听导航页面切换,控制播放栏显示隐藏
extension CustomNavigationController: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        // 判断当前页面是否是需要排除的详情页(替换成你的详情VC类名)
        let shouldHideBar = viewController is DetailViewController
        nowPlayingBarVC?.view.isHidden = shouldHideBar
    }
}

3. 配置项目使用自定义导航控制器

  • 在Storyboard里,把原来的UINavigationController替换成CustomNavigationController
  • 确保所有需要显示播放栏的页面都在这个导航控制器的栈中,详情页也通过这个导航控制器push/pop,这样切换时会自动触发播放栏的显示/隐藏

4. 同步播放状态与UI

要让播放栏实时更新歌曲信息和播放状态,推荐用通知中心实现:

  • 在NowPlayingBarViewController里监听播放状态变化的通知:
override func viewDidLoad() {
    super.viewDidLoad()
    // 监听播放更新通知
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(updateNowPlayingUI),
        name: NSNotification.Name("NowPlayingStatusUpdated"),
        object: nil
    )
}

@objc private func updateNowPlayingUI(_ notification: Notification) {
    // 从通知userInfo中获取数据更新UI
    if let song = notification.userInfo?["currentSong"] as? SongModel {
        songNameLabel.text = song.title
        artistLabel.text = song.artist
        albumCoverImageView.image = song.coverImage
    }
    let isPlaying = notification.userInfo?["isPlaying"] as? Bool ?? false
    playPauseButton.setImage(
        isPlaying ? UIImage(systemName: "pause.fill") : UIImage(systemName: "play.fill"),
        for: .normal
    )
}

// 记得移除监听
deinit {
    NotificationCenter.default.removeObserver(self)
}
  • 在你的播放管理器(比如AudioPlayerManager)中,当歌曲切换或播放状态改变时发送通知:
func updatePlayingStatus(song: SongModel, isPlaying: Bool) {
    NotificationCenter.default.post(
        name: NSNotification.Name("NowPlayingStatusUpdated"),
        object: nil,
        userInfo: [
            "currentSong": song,
            "isPlaying": isPlaying
        ]
    )
}

额外注意点

  • 如果你的App用了TabBarController,需要让TabBar的每个子控制器都使用这个自定义导航控制器,保证所有页面都能统一控制播放栏
  • 播放栏的点击事件(比如跳转到播放详情页)可以在NowPlayingBarViewController里添加按钮点击方法,通过导航控制器push对应的页面
  • 可以给播放栏添加毛玻璃效果:给播放栏的View添加UIVisualEffectView作为子View,设置为系统的模糊效果,更贴近苹果音乐的风格

内容的提问来源于stack exchange,提问作者Jacob Cavin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:10:52