9 浮動視窗
9.1 概述
浮動視窗功能是指支援播放器在一個可拖動位置、可改變大小、視圖層級位於最頂層的視窗進行播放。我們在 demo 中提供了兩種浮動視窗出現的互動,一種是當頁面滾動到(固定在頁面頂部的)播放器底部消失時,出現浮動小視窗並繼續播放影片,大播放器出現時,浮動視窗消失;另一種是點擊播放器皮膚上的浮動視窗按鈕,導航回上個頁面,影片在浮動視窗上繼續播放。
9.2 快速整合
9.2.1 SDK 版本
浮動視窗功能不涉及 SDK 的改動,使用該功能無需升級到特定的 SDK 版本,不過開發該功能時使用的 SDK 版本是 2.8.0,建議不要使用版本落差太大的版本,以免產生不必要的問題,該功能的測試均基於 v2.8.0 的 SDK。
9.2.2 開源程式碼
浮動視窗功能程式碼全部都是開源的,位於 demo 專案的資料夾 PolyvOpenSourceModule/Floating 中,請把 demo 的程式碼更新到版本 2.8.0 以上,然後把這個資料夾下的程式碼拖到你的專案中。該資料夾下的檔案目錄如下:
├── Floating
├── PLVVFloatingPlayerViewController.h/m
├── Resource
└── FloatingWindow
├── PLVVFloatingWindow.h/m
├── PLVVFloatingWindowSkin.h/m
└── PLVVFloatingWindowViewController.h/m
資料夾 Resource 下面是浮動視窗功能所需要的資源檔案,FloatingWindow 是浮動視窗的所有程式碼,PLVVFloatingPlayerViewController 類別為浮動視窗功能範例程式碼,建議在我們的範例程式碼基礎上進行整合。
同時,需將 PolyvOpenSourceModule/Skin 資料夾下的程式碼也更新到 2.8.0 版本以上,以支援浮動視窗功能。
9.2.3 demo 範例
在影片列表頁面加入以下標頭檔:
#import "PLVVFloatingPlayerViewController.h"
#import "PLVVFloatingWindow.h"
PLVVFloatingPlayerViewController 類別有兩個初始化方法:
-initWithPlayer:目前已出現浮動視窗且播放影片 vid 相同時使用。-initWithVid:目前未出現浮動視窗,或浮動視窗播放影片與即將播放影片 vid 不同。
使用這兩個方法進行頁面跳轉的程式碼範例如下,詳細可參考 PLVAccountVideoListController 類別。
PLVVFloatingWindow *window = [PLVVFloatingWindow sharedInstance];
PLVVodSkinPlayerController *player = window.contentVctrl.player;
NSString *playingVid = window.contentVctrl.vid;
NSString *vid; // 从视频列表中选中并即将播放的视频 vid
if (player && playingVid && [playingVid isEqualToString:vid]) {
PLVVFloatingPlayerViewController *vctrl = [[PLVVFloatingPlayerViewController alloc] initWithPlayer:player];
[self.navigationController pushViewController:vctrl animated:YES];
} else {
PLVVFloatingPlayerViewController *vctrl = [[PLVVFloatingPlayerViewController alloc] initWithVid:vid];
[self.navigationController pushViewController:vctrl animated:YES];
}
9.3 浮動視窗視窗
浮動視窗視窗 PLVVFloatingWindow 是 UIWindow 類別單例,windowLevel 為 UIWindowLevelNormal + 1,預設 hidden 屬性為 YES。浮動視窗寬高比為 16:9,視窗寬度預設為螢幕寬度的 1/2。
按住浮動視窗左上角可進行縮放,視窗寬度的縮放範圍為大於 160 pt,小於螢幕寬。使用以下方法可使視窗恢復初始尺寸、初始位置。
// 悬浮窗回到初始尺寸、初始位置
- (void)reset;
9.4 浮動視窗視窗控制器
PLVVFloatingWindowViewController 為浮動視窗視窗的根控制器,可透過浮動視窗 PLVVFloatingWindow 的屬性 contentVctrl 取得:
PLVVFloatingWindowViewController *vctrl = [PLVVFloatingWindow sharedInstance].contentVctrl;
控制器 PLVVFloatingWindowViewController 的唯讀屬性 vid、player 除了能用於取得目前浮動視窗持有的播放器(如果有的話)以及播放影片的 vid,還可用於判斷目前浮動視窗是否正在播放影片,沒有播放影片時這兩個屬性值均為 $nil$。
// 悬浮窗正在播放视频 vid,悬浮窗没有播放视频时为 nil,默认值为 nil
@property (nonatomic, strong, readonly) NSString * _Nullable vid;
// 悬浮窗持有的视频播放器,悬浮窗没有播放视频时为 nil,默认值为 nil
@property (nonatomic, strong, readonly) PLVVodSkinPlayerController * _Nullable player;
以下方法用於把頁面上的播放器置於浮動視窗上,使用範例詳見類別 PLVVFloatingPlayerViewController:
// vctrl 为持有大播放器的页面,当退出当前播放页面进行悬浮窗播放时 vctrl 为 nil
- (void)addPlayer:(PLVVodSkinPlayerController *)player partnerViewController:(id<PLVVFloatingWindowProtocol> _Nullable)vctrl;
其中,PLVVFloatingWindowProtocol 規定了使用浮動視窗的頁面需要遵循的協定。
@protocol PLVVFloatingWindowProtocol <NSObject>
// 悬浮窗【exchange】按钮响应回调
- (void)exchangePlayer;
@end
以下方法用於移除或銷毀浮動視窗播放器:
// 销毁并移除悬浮窗口持有的播放器
- (void)destroyPlayer;
// 将悬浮窗上的播放器移走,但是不销毁
- (void)removePlayer;
控制器 PLVVFloatingWindowViewController 還定義了以下廣播事件,在進入/退出浮動視窗模式時會發送廣播到所有 observer。
// 进入悬浮窗模式广播事件
extern NSString *PLVVFloatingWindowEnterNotification;
// 退出悬浮窗模式广播事件
extern NSString *PLVVFloatingWindowLeaveNotification;
9.5 浮動視窗視窗皮膚
浮動視窗播放器的皮膚 PLVVFloatingWindowSkin 由浮動視窗的根控制器 PLVVFloatingWindowViewController 持有,包含了【關閉浮動視窗】按鈕、【Exchange】按鈕、【播放/暫停】按鈕。浮動視窗播放器皮膚的持有者需遵循協定 PLVVFloatingWindowSkinProtocol 作為 delegate 以響應皮膚上的按鈕:
/// 悬浮窗播放器控制按钮层响应事件回调
@protocol PLVVFloatingWindowSkinProtocol <NSObject>
- (void)tapCloseButton;
- (void)tapExchangeButton;
- (void)tapPlayButton:(BOOL)play;
@end
@interface PLVVFloatingWindowSkin : UIView
@property (nonatomic, weak) id<PLVVFloatingWindowSkinProtocol> delegate;
@end
此外,透過 SDK 播放器類別 PLVVodPlayerViewController 的播放狀態回呼 playbackStateHandler,呼叫方法 -statusIsPlaying: 即時更新皮膚上【播放/暫停】按鈕的狀態:
__weak typeof(self) weakSelf = self;
self.player.playbackStateHandler = ^(PLVVodPlayerViewController *player) {
[weakSelf.windowSkin statusIsPlaying:(player.playbackState == PLVVodPlaybackStatePlaying)];
};
self.windowSkin 為浮動視窗播放器皮膚的實例物件,self.player 為 PLVVodPlayerViewController 的實例物件。
