在 iOS 中模拟 YouTube 迷你播放器

Emulating YouTube Mini Player in iOS

在 YouTube 应用程序中,我可以通过位于最底部 right-hand 角落的 mini-player 继续观看视频(参见下面标题为 "The Chainsmokers" 的视频)当我浏览应用程序时,其他视图控制器。无论我在哪个页面,我都可以在迷你播放器中观看视频。

如果您从迷你播放器向上拖动,将显示视频的整个视图控制器。但它总是在其他页面的顶部。我正在尝试了解如何使用 Swift 复制此方法,以便我可以从任何页面观看视频。

我的应用程序的结构方式是通过 UIPageViewController。我嵌入了三个独特的导航控制器(用于滑动导航目的(参见下面的代码))。我想了解如何使用 mini-player。在 YouTube 中,它像一个迷你模式 VC 吗?它在结构上是如何布局的,如果您知道,我该如何将其整合到我当前的布局中?

class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    private var pages: [UINavigationController]!

    private var currentPageIndex: Int!

    override func viewDidLoad() {
        super.viewDidLoad()
            self.dataSource = self
            self.delegate = self

            self.pages = [
                self.storyboard!.instantiateViewControllerWithIdentifier("Nav1") as! UINavigationController,
                self.storyboard!.instantiateViewControllerWithIdentifier("Nav2") as! UINavigationController,
                self.storyboard!.instantiateViewControllerWithIdentifier("Nav3") as! UINavigationController
            ]

            (self.pages[0].topViewController as! Nav1).parentPageViewController = self
            (self.pages[1].topViewController as! Nav2).parentPageViewController = self
            (self.pages[2].topViewController as! Nav3).parentPageViewController = self


            self.currentPageIndex = 1
            let startingViewController = self.pages[1] as UINavigationController
            self.setViewControllers([startingViewController], direction: .Forward, animated: false, completion: nil)
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        let index = (self.pages as NSArray).indexOfObject(viewController)
        self.currentPageIndex = index

        // if currently displaying last view controller, return nil to indicate that there is no next view controller
        return (self.currentPageIndex == self.pages.count - 1 ? nil : self.pages[self.currentPageIndex + 1])
    }
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        let index = (self.pages as NSArray).indexOfObject(viewController)
        self.currentPageIndex = index

        // if currently displaying first view controller, return nil to indicate that there is no previous view controller
        return (index == 0 ? nil : self.pages[index - 1])
    }
func displayPageForIndex(index: Int, animated: Bool = true) {
        assert(index >= 0 && index < self.pages.count, "Error: Attempting to display a page for an out of bounds index")

        // nop if index == self.currentPageIndex
        if self.currentPageIndex == index { return }

        if index < self.currentPageIndex {
            self.setViewControllers([self.pages[index]], direction: .Reverse, animated: true, completion: nil)
        } else if index > self.currentPageIndex {
            self.setViewControllers([self.pages[index]], direction: .Forward, animated: true, completion: nil)
        }

        self.currentPageIndex = index
    }

}

这很容易做到。您将子 class UIWindow,添加一个迷你播放器视图并确保它始终位于视图层次结构的顶部。首先在您的 AppDelegate 中添加此代码以覆盖您的 window:

/*!
 *  Subclassing UIWindow
 */
-(UIWindow *)window
{
    static YourWindow *customWindow = nil;
    if (!customWindow) customWindow = [[YourWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    return customWindow;
}

现在在 YourWindow class 中添加 miniPlayer:

-(void)awakeFromNib
{
    [self addMiniPlayer];
}

-(void)addMiniPlayer
{
    UIView *miniPlayer = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)]; //change to your frame here
    [self addSubview:miniPlayer];
    miniPlayer.backgroundColor = [UIColor redColor];
    self.miniPlayer = miniPlayer;
}

-(void)layoutSubviews
{
    [super layoutSubviews];
    [self bringSubviewToFront:self.miniPlayer];

    // You would like to update your miniplayer frame here.
    //CGRect frame = self.miniPlayer.frame;
    //frame.origin.x = self.frame.size.width - frame.size.width - 5;
    //frame.origin.y = 70;
    //self.appInfoLabel.frame = frame;
} 

现在您的工作是调整 miniPlayer 的行为。您可以从 AppDelegate 访问它,如下所示:self.window.miniPlayer

更新:这是 Swift 编写的示例:https://github.com/sahara108/TestCustomWindow