Installation
# Player with default control layer.
pod 'SJVideoPlayer'
# The base player, without the control layer, can be used if you need a custom control layer. 需要自己定義播放UI時(shí)使用
pod 'SJBaseVideoPlayer'
天朝
# 如果網(wǎng)絡(luò)不行安裝不了, 可改成以下方式進(jìn)行安裝
pod 'SJBaseVideoPlayer', :git => 'https://gitee.com/changsanjiang/SJBaseVideoPlayer.git'
pod 'SJVideoPlayer', :git => 'https://gitee.com/changsanjiang/SJVideoPlayer.git'
pod 'SJUIKit/AttributesFactory', :git => 'https://gitee.com/changsanjiang/SJUIKit.git'
pod 'SJUIKit/ObserverHelper', :git => 'https://gitee.com/changsanjiang/SJUIKit.git'
pod 'SJUIKit/Queues', :git => 'https://gitee.com/changsanjiang/SJUIKit.git'
$ pod update --no-repo-update (不要用 pod install 了, 用這個(gè)命令安裝)
Example 使用示例
_player = [SJVideoPlayer player];
_player.view.frame = CGRectMake(0, 0, 200, 200);
[self.view addSubview:_player.view];
// 設(shè)置資源進(jìn)行播放
_player.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithURL:URL];
... 等等, 更多設(shè)置, 請查看頭文件. 相應(yīng)功能均為懶加載, 用到時(shí)才會創(chuàng)建.
Documents
1. 視圖層次結(jié)構(gòu)
- 1.1 UIView
- 1.2 UITableView中的層次結(jié)構(gòu)
- 1.2.1 UITableViewCell
- 1.2.2 UITableView.tableHeaderView
- 1.2.3 UITableView.tableFooterView
- 1.2.4 UITableViewHeaderFooterView
- 1.3 UICollectionView 中的層次結(jié)構(gòu)
- 1.3.1 UICollectionViewCell
- 1.4 嵌套時(shí)的層次結(jié)構(gòu)
- 1.4.1 UICollectionView 嵌套在 UITableViewCell 中
- 1.4.2 UICollectionView 嵌套在 UITableViewHeaderView 中
- 1.4.3 UICollectionView 嵌套在 UICollectionViewCell 中
2. URLAsset
3. 播放控制
- 3.1 播放
- 3.2 暫停
- 3.3 刷新
- 3.4 重播
- 3.5 停止
- 3.6 靜音
- 3.7 調(diào)速
- 3.8 報(bào)錯
- 3.9 跳轉(zhuǎn)
- 3.10 切換清晰度
- 3.11 當(dāng)前時(shí)間
- 3.12 總時(shí)長
- 3.13 緩沖時(shí)長
- 3.14 是否已播放完畢
- 3.15 是否調(diào)用過播放
- 3.16 是否調(diào)用過重播
- 3.17 設(shè)置新資源時(shí), 是否自動播放
- 3.18 進(jìn)入后臺, 是否暫停播放
- 3.19 進(jìn)入前臺, 是否恢復(fù)播放
- 3.20 跳轉(zhuǎn)完成, 是否恢復(fù)播放
- 3.21 資源準(zhǔn)備狀態(tài)
- 3.22 播放控制狀態(tài)
- 3.23 播放等待的原因
- 3.24 監(jiān)聽狀態(tài)改變??
- 3.25 已觀看的時(shí)長(當(dāng)前資源)
- 3.26 接入別的視頻 SDK, 自己動手?jǐn)]一個(gè) SJVideoPlayerPlaybackController, 替換作者原始實(shí)現(xiàn)
4. 控制層的顯示和隱藏
5. 設(shè)備亮度和音量
6. 旋轉(zhuǎn)
7. 直接全屏而不旋轉(zhuǎn)
8. 鏡像翻轉(zhuǎn)
9. 網(wǎng)絡(luò)狀態(tài)
10. 手勢
11. 占位圖
12. 顯示提示文本
13. 一些固定代碼
14. 截屏
15. 導(dǎo)出視頻或GIF
16. 滾動相關(guān)
17. 自動播放 - 在 UICollectionView 或者 UITableView 中
18. 對控制層上的Item的操作
19. 對控制層上的Item的一些補(bǔ)充
20. SJEdgeControlLayer 的補(bǔ)充
以下為詳細(xì)介紹:
1.1 UIView
1.1 UIView
_player = [SJVideoPlayer player];
_player.view.frame = ...;
[self.view addSubview:_player.view];
// 設(shè)置資源進(jìn)行播放
SJVideoPlayerURLAsset *asset = [[SJVideoPlayerURLAsset alloc] initWithURL:URL];
_player.URLAsset = asset;
在普通視圖中播放時(shí), 不需要指定視圖層次, 直接創(chuàng)建資源進(jìn)行播放即可.
1.2 UITableView 中的層次結(jié)構(gòu)
由于 UITableView 及 UICollectionView 的復(fù)用機(jī)制, 會導(dǎo)致播放器視圖顯示在錯誤的位置上, 為防止出現(xiàn)此種情況, 在創(chuàng)建資源時(shí)指定視圖層次結(jié)構(gòu), 使得播放器能夠定位具體的父視圖, 依此來控制隱藏與顯示.
1.2.1 UITableViewCell
-- UITableView
-- UITableViewCell
-- Player.superview
-- Player.view
_player = [SJVideoPlayer player];
UIView *playerSuperview = cell.coverImageView;
SJPlayModel *playModel = [SJPlayModel UITableViewCellPlayModelWithPlayerSuperviewTag:playerSuperview.tag atIndexPath:indexPath tableView:self.tableView];
_player.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithURL:URL playModel:playModel];
在 UITableViewCell 中播放時(shí), 需指定 Cell 所處的 indexPath 以及播放器父視圖的 tag.
在滑動時(shí), 管理類將會通過這兩個(gè)參數(shù)控制播放器父視圖的顯示與隱藏.
1.2.2 UITableView.tableHeaderView
-- UITableView
-- UITableView.tableHeaderView 或者 UITableView.tableFooterView
-- Player.superview
-- Player.view
UIView *playerSuperview = self.tableView.tableHeaderView;
// 也可以設(shè)置子視圖
// playerSuperview = self.tableView.tableHeaderView.coverImageView;
SJPlayModel *playModel = [SJPlayModel UITableViewHeaderViewPlayModelWithPlayerSuperview:playerSuperview tableView:self.tableView];
1.2.4 UITableViewHeaderFooterView
-- UITableView
-- UITableViewHeaderFooterView
-- Player.superview
-- Player.view
/// isHeader: 當(dāng)在header中播放時(shí), 傳YES, 在footer時(shí), 傳NO.
SJPlayModel *playModel = [SJPlayModel UITableViewHeaderFooterViewPlayModelWithPlayerSuperviewTag:sectionHeaderView.coverImageView.tag inSection:section isHeader:YES tableView:self.tableView];
1.3 UICollectionView 中的層次結(jié)構(gòu)
1.3.1 UICollectionViewCell
-- UICollectionView
-- UICollectionViewCell
-- Player.superview
-- Player.view
SJPlayModel *playModel = [SJPlayModel UICollectionViewCellPlayModelWithPlayerSuperviewTag:cell.coverImageView.tag atIndexPath:indexPath collectionView:self.collectionView];
1.4 嵌套時(shí)的視圖層次
嵌套的情況下, 傳遞的參數(shù)比較多, 不過熟悉了前面的套路, 下面的這些也不成問題. (會被復(fù)用的視圖, 傳 tag. 如果不會被復(fù)用, 則直接傳視圖)
1.4.1 UICollectionView 嵌套在 UITableViewCell 中
-- UITableView
-- UITableViewCell
-- UITableViewCell.UICollectionView
-- UICollectionViewCell
-- Player.superview
-- Player.view
SJPlayModel *playModel = [SJPlayModel UICollectionViewNestedInUITableViewCellPlayModelWithPlayerSuperviewTag:collectionViewCell.coverImageView.tag atIndexPath:collectionViewCellAtIndexPath collectionViewTag:tableViewCell.collectionView.tag collectionViewAtIndexPath:tableViewCellAtIndexPath tableView:self.tableView];
1.4.2 UICollectionView 嵌套在 UITableViewHeaderView 中
-- UITableView
-- UITableView.tableHeaderView 或者 UITableView.tableFooterView
-- tableHeaderView.UICollectionView
-- UICollectionViewCell
-- Player.superview
-- Player.view
SJPlayModel *playModel = [SJPlayModel UICollectionViewNestedInUITableViewHeaderViewPlayModelWithPlayerSuperviewTag:cell.coverImageView.tag atIndexPath:indexPath collectionView:tableHeaderView.collectionView tableView:self.tableView];
1.4.3 UICollectionView 嵌套在 UICollectionViewCell 中
-- UICollectionView
-- UICollectionViewCell
-- UICollectionViewCell.UICollectionView
-- UICollectionViewCell
-- Player.superview
-- Player.view
SJPlayModel *playModel = [SJPlayModel UICollectionViewNestedInUICollectionViewCellPlayModelWithPlayerSuperviewTag:collectionViewCell.coverImageView.tag atIndexPath:collectionViewCellAtIndexPath collectionViewTag:rootCollectionViewCell.collectionView.tag collectionViewAtIndexPath:collectionViewAtIndexPath rootCollectionView:self.collectionView];
2. URLAsset
播放器 播放的資源是通過 SJVideoPlayerURLAsset 創(chuàng)建的. SJVideoPlayerURLAsset 由兩部分組成:
視圖層次 (第一部分中的SJPlayModel) 資源地址 (可以是本地資源/URL/AVAsset)
默認(rèn)情況下, 創(chuàng)建了 SJVideoPlayerURLAsset , 賦值給播放器后即可播放.
2.1 播放 URL(本地文件或遠(yuǎn)程資源)
NSURL *URL = [NSURL URLWithString:@"https://...example.mp4"];
_player.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithURL:URL];
2.3 從指定的位置開始播放
NSTimeInterval secs = 20.0;
_player.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithURL:URL specifyStartTime:secs]; // 直接從20秒處開始播放
2.4 續(xù)播(進(jìn)入下個(gè)頁面時(shí), 繼續(xù)播放)
我們可能需要切換界面時(shí), 希望視頻能夠在下一個(gè)界面無縫的進(jìn)行播放. 使用如下方法, 傳入正在播放的資源, 將新的資源賦值給播放器播放即可.
// otherAsset 即為上一個(gè)頁面播放的Asset
// 除了需要一個(gè)otherAsset, 其他方面同以上的示例一模一樣
_player.URLAsset = [SJVideoPlayerURLAsset.alloc initWithOtherAsset:otherAsset];
2.5 銷毀時(shí)的回調(diào). 可在此做一些記錄工作, 如播放記錄
// 每個(gè)資源dealloc時(shí)的回調(diào)
_player.assetDeallocExeBlock = ^(__kindof SJBaseVideoPlayer * _Nonnull videoPlayer) {
// .....
};
當(dāng)資源銷毀時(shí), 播放器將會回調(diào)該 block.
3. 播放控制
播放控制: 對播放進(jìn)行的操作. 此部分的內(nèi)容由 "id <SJMediaPlaybackController> playbackController" 提供支持.
大多數(shù)對播放進(jìn)行的操作, 均在協(xié)議 SJMediaPlaybackController 進(jìn)行了聲明.
正常來說實(shí)現(xiàn)了此協(xié)議的任何對象, 均可賦值給 player.playbackController 來替換原始實(shí)現(xiàn).
3.1 播放
[_player play];
3.2 暫停
[_player pause];
3.3 刷新
在播放一個(gè)資源時(shí), 可能有一些意外情況導(dǎo)致播放失敗(如網(wǎng)絡(luò)環(huán)境差).
此時(shí)當(dāng)用戶點(diǎn)擊刷新按鈕, 我們需要對當(dāng)前的資源(Asset)進(jìn)行刷新.
SJBaseVideoPlayer提供了直接的方法去刷新, 不需要開發(fā)者再重復(fù)的去創(chuàng)建新的Asset.
[_player refresh];
3.4 重播
從頭開始重新播放
[_player replay];
3.5 停止
停止播放, 請注意: 當(dāng)前資源將會被清空, 如需重播, 請重新設(shè)置新資源
[_player stop];
3.6 靜音
_player.muted = YES;
3.7 調(diào)速
// 默認(rèn)值為 1.0
_player.rate = 1.0;
3.8 報(bào)錯
當(dāng)播放發(fā)生錯誤時(shí), 可以通過它來獲取錯誤信息
_player.error
3.9 跳轉(zhuǎn)
///
/// 是否精確跳轉(zhuǎn), default value is NO.
///
@property (nonatomic) BOOL accurateSeeking;
///
/// 跳轉(zhuǎn)到指定位置播放
///
- (void)seekToTime:(NSTimeInterval)secs completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;
- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;
3.10 切換清晰度
<pre style="box-sizing: border-box; overflow: auto; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 13.6px; margin-top: 0px; margin-bottom: 0px; overflow-wrap: normal; padding: 16px; line-height: 1.45; background-color: rgb(246, 248, 250); border-radius: 3px; word-break: normal; tab-size: 4; color: rgb(51, 51, 51);">///
/// 切換清晰度
///
- (void)switchVideoDefinition:(SJVideoPlayerURLAsset *)URLAsset;
///
/// 當(dāng)前清晰度切換的信息
///
@property (nonatomic, strong, readonly) SJVideoDefinitionSwitchingInfo *definitionSwitchingInfo;
/// 以下為設(shè)置 SJVideoPlayer.definitionURLAssets, 將會在清晰度切換控制層中顯示這些資源項(xiàng).
SJVideoPlayerURLAsset *asset1 = [[SJVideoPlayerURLAsset alloc] initWithURL:VideoURL_Level4];
asset1.definition_fullName = @"超清 1080P";
asset1.definition_lastName = @"超清";
SJVideoPlayerURLAsset *asset2 = [[SJVideoPlayerURLAsset alloc] initWithURL:VideoURL_Level3];
asset2.definition_fullName = @"高清 720P";
asset2.definition_lastName = @"AAAAAAA";
SJVideoPlayerURLAsset *asset3 = [[SJVideoPlayerURLAsset alloc] initWithURL:VideoURL_Level2];
asset3.definition_fullName = @"清晰 480P";
asset3.definition_lastName = @"480P";
_player.definitionURLAssets = @[asset1, asset2, asset3];
// 先播放asset1\. (asset2 和 asset3 將會在用戶選擇后進(jìn)行切換)
_player.URLAsset = asset1;</pre>
### [](https://gitee.com/changsanjiang/SJVideoPlayer#311)
3.11 當(dāng)前時(shí)間
@property (nonatomic, readonly) NSTimeInterval currentTime; ///< 當(dāng)前播放到的時(shí)間
3.12 總時(shí)長
@property (nonatomic, readonly) NSTimeInterval duration; ///< 總時(shí)長
3.13 緩沖時(shí)長
@property (nonatomic, readonly) NSTimeInterval playableDuration; ///< 緩沖到的時(shí)間
3.14 是否已播放完畢
@property (nonatomic, readonly) BOOL isPlayedToEndTime; ///< 當(dāng)前資源是否已播放結(jié)束
3.15 是否調(diào)用過播放
@property (nonatomic, readonly) BOOL isPlayed; ///< 是否播放過當(dāng)前的資源
3.16 是否調(diào)用過重播
@property (nonatomic, readonly) BOOL isReplayed; ///< 是否重播過當(dāng)前的資源
3.17 設(shè)置新資源時(shí), 是否自動播放
@property (nonatomic) BOOL autoplayWhenSetNewAsset; ///< 設(shè)置新的資源后, 是否自動調(diào)用播放. 默認(rèn)為 YES
3.18 進(jìn)入后臺, 是否暫停播放
關(guān)于后臺播放視頻, 引用自: https://juejin.im/post/5a38e1a0f265da4327185a26
當(dāng)您想在后臺播放視頻時(shí):
1.需要設(shè)置 videoPlayer.pauseWhenAppDidEnterBackground = NO; (該值默認(rèn)為YES, 即App進(jìn)入后臺默認(rèn)暫停).
2.前往 TARGETS -> Capability -> enable Background Modes -> select this mode Audio, AirPlay, and Picture in Picture
_player.pauseWhenAppDidEnterBackground = NO; // 默認(rèn)值為 YES, 即進(jìn)入后臺后 暫停.
3.19 進(jìn)入前臺, 是否恢復(fù)播放
@property (nonatomic) BOOL resumePlaybackWhenAppDidEnterForeground; ///< 進(jìn)入前臺時(shí), 是否恢復(fù)播放. 默認(rèn)為 NO
3.20 跳轉(zhuǎn)完成, 是否恢復(fù)播放
@property (nonatomic) BOOL resumePlaybackWhenPlayerHasFinishedSeeking; ///< 當(dāng)`seekToTime:`操作完成后, 是否恢復(fù)播放. 默認(rèn)為 YES
3.21 資源準(zhǔn)備狀態(tài)
資源準(zhǔn)備(或初始化)的狀態(tài)
當(dāng)未設(shè)置資源時(shí), 此時(shí) player.assetStatus = .unknown 當(dāng)設(shè)置新資源時(shí), 此時(shí) player.assetStatus = .preparing 當(dāng)準(zhǔn)備好播放時(shí), 此時(shí) player.assetStatus = .readyToPlay 當(dāng)初始化失敗時(shí), 此時(shí) player.assetStatus = .failed
typedef NS_ENUM(NSInteger, SJAssetStatus) {
///
/// 未知狀態(tài)
///
SJAssetStatusUnknown,
///
/// 準(zhǔn)備中
///
SJAssetStatusPreparing,
///
/// 當(dāng)前資源可隨時(shí)進(jìn)行播放(播放控制請查看`timeControlStatus`)
///
SJAssetStatusReadyToPlay,
///
/// 發(fā)生錯誤
///
SJAssetStatusFailed
};
3.22 播放控制狀態(tài)
暫?;虿シ诺目刂茽顟B(tài)
當(dāng)調(diào)用了暫停時(shí), 此時(shí) player.timeControlStatus = .paused
當(dāng)調(diào)用了播放時(shí), 此時(shí) 將可能處于以下兩種狀態(tài)中的任意一個(gè):
player.timeControlStatus = .playing 正在播放中.
player.timeControlStatus = .waitingToPlay 等待播放, 等待的原因請查看 player.reasonForWaitingToPlay
typedef NS_ENUM(NSInteger, SJPlaybackTimeControlStatus) {
///
/// 暫停狀態(tài)(已調(diào)用暫?;蛭磮?zhí)行任何操作的狀態(tài))
///
SJPlaybackTimeControlStatusPaused,
///
/// 播放狀態(tài)(已調(diào)用播放), 當(dāng)前正在緩沖或正在評估能否播放. 可以通過`reasonForWaitingToPlay`來獲取原因, UI層可以根據(jù)原因來控制loading視圖的狀態(tài).
///
SJPlaybackTimeControlStatusWaitingToPlay,
///
/// 播放狀態(tài)(已調(diào)用播放), 當(dāng)前播放器正在播放
///
SJPlaybackTimeControlStatusPlaying
};
3.23 播放等待的原因
當(dāng)調(diào)用了播放, 播放器未能播放處于等待狀態(tài)時(shí)的原因
等待原因有以下3種狀態(tài): 1.未設(shè)置資源, 此時(shí)設(shè)置資源后, 當(dāng)player.assetStatus = .readyToPlay, 播放器將自動進(jìn)行播放. 2.可能是由于緩沖不足, 播放器在等待緩存足夠時(shí)自動恢復(fù)播放, 此時(shí)可以顯示loading視圖. 3.可能是正在評估緩沖中, 這個(gè)過程會進(jìn)行的很快, 不需要顯示loading視圖.
///
/// 緩沖中, UI層建議顯示loading視圖
///
extern SJWaitingReason const SJWaitingToMinimizeStallsReason;
///
/// 正在評估能否播放, 處于此狀態(tài)時(shí), 不建議UI層顯示loading視圖
///
extern SJWaitingReason const SJWaitingWhileEvaluatingBufferingRateReason;
///
/// 未設(shè)置資源
///
extern SJWaitingReason const SJWaitingWithNoAssetToPlayReason;
3.24 監(jiān)聽狀態(tài)改變??
///
/// 觀察者
///
/// 可以如下設(shè)置block, 來監(jiān)聽某個(gè)狀態(tài)的改變
/// 了解更多請前往頭文件查看
/// player.playbackObserver.currentTimeDidChangeExeBlock = ...;
/// player.playbackObserver.durationDidChangeExeBlock = ...;
/// player.playbackObserver.timeControlStatusDidChangeExeBlock = ...;
///
@property (nonatomic, strong, readonly) SJPlaybackObservation *playbackObserver;
3.25 已觀看的時(shí)長(當(dāng)前資源)
@property (nonatomic, readonly) NSTimeInterval durationWatched; ///< 已觀看的時(shí)長(當(dāng)前資源)
3.26 接入別的視頻 SDK, 自己動手?jǐn)]一個(gè) SJVideoPlayerPlaybackController, 替換作者原始實(shí)現(xiàn)
某些時(shí)候, 我們需要接入第三方的視頻SDK, 但是又想使用 SJBaseVideoPlayer 封裝的其他的功能.
這個(gè)時(shí)候, 我們可以自己動手, 將第三方的SDK封裝一下, 實(shí)現(xiàn) SJVideoPlayerPlaybackController 協(xié)議, 管理 SJBaseVideoPlayer 中的播放操作.
示例:
- 可以參考 SJAVMediaPlaybackController 中的實(shí)現(xiàn).
- 封裝 ijkplayer 的示例: https://gitee.com/changsanjiang/SJIJKMediaPlaybackController
_player.playbackController = Your PlaybackController.
4. 控制層的顯示和隱藏
控制層的顯示和隱藏, 此部分的內(nèi)容由 "id <SJControlLayerAppearManager> controlLayerAppearManager" 提供支持.
controlLayerAppearManager 內(nèi)部存在一個(gè)定時(shí)器, 當(dāng)控制層顯示時(shí), 會開啟此定時(shí)器. 一定間隔后, 會嘗試隱藏控制層.
其他相關(guān)操作, 請見以下內(nèi)容.
4.1 讓控制層顯示
當(dāng)控制層需要顯示時(shí), 可以調(diào)用下面方法.
[_player controlLayerNeedAppear];
此方法將會回調(diào)控制層的代理方法:
"- (void)controlLayerNeedAppear:(__kindof SJBaseVideoPlayer *)videoPlayer;"
代理將會對當(dāng)前的控制層進(jìn)行顯示處理.
4.2 讓控制層隱藏
當(dāng)控制層需要隱藏時(shí), 可以調(diào)用下面方法.
[_player controlLayerNeedDisappear];
此方法將會回調(diào)控制層的代理方法:
"- (void)controlLayerNeedDisappear:(__kindof SJBaseVideoPlayer *)videoPlayer;"
代理將會對當(dāng)前的控制層進(jìn)行隱藏處理.
4.3 控制層是否顯示中
///
/// 控制層的顯示狀態(tài)(是否已顯示)
///
@property (nonatomic, getter=isControlLayerAppeared) BOOL controlLayerAppeared;
4.4 是否在暫停時(shí)保持控制層顯示
///
/// 暫停的時(shí)候是否保持控制層顯示
///
/// default value is NO
///
@property (nonatomic) BOOL pausedToKeepAppearState;
4.5 監(jiān)聽狀態(tài)改變??
///
/// 觀察者
///
/// 當(dāng)需要監(jiān)聽控制層的顯示和隱藏時(shí), 可以設(shè)置`player.controlLayerAppearObserver.appearStateDidChangeExeBlock = ...;`
///
@property (nonatomic, strong, readonly) id<SJControlLayerAppearManagerObserver> controlLayerAppearObserver;
4.6 自己動手?jǐn)]一個(gè) SJControlLayerAppearManager, 替換作者原始實(shí)現(xiàn)
同樣的, 協(xié)議 "SJControlLayerAppearManager" 定義了一系列的操作, 只要實(shí)現(xiàn)了這些協(xié)議方法的對象, 就可以管理控制層的顯示和隱藏.
_player.controlLayerAppearManager = Your controlLayerAppearManager;
5. 設(shè)備亮度和音量
設(shè)備亮度和音量的調(diào)整, 此部分的內(nèi)容由 "id <SJDeviceVolumeAndBrightnessManager> deviceVolumeAndBrightnessManager" 提供支持.
5.1 調(diào)整設(shè)備亮度
// 0 到 1
_player.deviceVolumeAndBrightnessManager.brightness = 1.0;
5.2 調(diào)整設(shè)備聲音
// 0 到 1
_player.deviceVolumeAndBrightnessManager.volume = 1.0;
5.3 監(jiān)聽狀態(tài)改變??
///
/// 觀察者
///
@property (nonatomic, strong, readonly) id<SJDeviceVolumeAndBrightnessManagerObserver> deviceVolumeAndBrightnessObserver;
5.4 禁止播放器設(shè)置
_player.disableBrightnessSetting = YES;
_player.disableVolumeSetting = YES;
5.5 自己動手?jǐn)]一個(gè) SJDeviceVolumeAndBrightnessManager, 替換作者原始實(shí)現(xiàn)
當(dāng)需要對設(shè)備音量視圖進(jìn)行自定義時(shí), 可以自己動手?jǐn)]一個(gè) SJDeviceVolumeAndBrightnessManager.
_player.deviceVolumeAndBrightnessManager = Your deviceVolumeAndBrightnessManager;
6. 旋轉(zhuǎn)
此部分的內(nèi)容由 "id <SJRotationManagerProtocol> rotationManager" 提供支持.
對于旋轉(zhuǎn), 我們開發(fā)者肯定需要絕對的控制, 例如: 設(shè)置自動旋轉(zhuǎn)所支持方向. 能夠主動+自動旋轉(zhuǎn), 而且還需要能在適當(dāng)?shù)臅r(shí)候禁止自動旋轉(zhuǎn). 旋轉(zhuǎn)前后的回調(diào)等等... 放心這些功能都有, 我挨個(gè)給大家介紹.
另外旋轉(zhuǎn)有兩種方式:
僅旋轉(zhuǎn)播放器視圖 (默認(rèn)情況下)
使 ViewController 也一起旋轉(zhuǎn)
具體請看下面介紹.
6.1 自動旋轉(zhuǎn)
先說說何為自動旋轉(zhuǎn). 其實(shí)就是當(dāng)設(shè)備方向變更時(shí), 播放器根據(jù)設(shè)備方向進(jìn)行自動旋轉(zhuǎn).
6.2 設(shè)置自動旋轉(zhuǎn)支持的方向
/// 設(shè)置自動旋轉(zhuǎn)支持的方向
_player.rotationManager.autorotationSupportedOrientations = SJOrientationMaskLandscapeLeft | SJOrientationMaskLandscapeRight;
/**
自動旋轉(zhuǎn)支持的方向
- SJOrientationMaskPortrait: 豎屏
- SJOrientationMaskLandscapeLeft: 支持全屏, Home鍵在右側(cè)
- SJOrientationMaskLandscapeRight: 支持全屏, Home鍵在左側(cè)
- SJOrientationMaskAll: 全部方向
*/
typedef enum : NSUInteger {
SJOrientationMaskPortrait = 1 << SJOrientation_Portrait,
SJOrientationMaskLandscapeLeft = 1 << SJOrientation_LandscapeLeft,
SJOrientationMaskLandscapeRight = 1 << SJOrientation_LandscapeRight,
SJOrientationMaskAll = SJOrientationMaskPortrait | SJOrientationMaskLandscapeLeft | SJOrientationMaskLandscapeRight,
} SJOrientationMask;
6.3 禁止自動旋轉(zhuǎn)
這里有兩點(diǎn)需要注意:
合適的時(shí)候要記得恢復(fù)自動旋轉(zhuǎn).
禁止自動旋轉(zhuǎn)后, 主動調(diào)用旋轉(zhuǎn), 還是可以旋轉(zhuǎn)的.
_player.rotationManager.disabledAutorotation = YES;
6.4 主動調(diào)用旋轉(zhuǎn)
主動旋轉(zhuǎn). 當(dāng)我們想主動旋轉(zhuǎn)時(shí), 大概分為以下三點(diǎn):
播放器旋轉(zhuǎn)到用戶當(dāng)前的設(shè)備方向或恢復(fù)小屏.
主動旋轉(zhuǎn)到指定方向.
主動旋轉(zhuǎn)完成后的回調(diào).
請看以下方法, 分別對應(yīng)以上三點(diǎn):
- (void)rotate;
- (void)rotate:(SJOrientation)orientation animated:(BOOL)animated;
- (void)rotate:(SJOrientation)orientation animated:(BOOL)animated completion:(void (^ _Nullable)(__kindof SJBaseVideoPlayer *player))block;
6.5 是否全屏
/// 如果為YES, 表示全屏
@property (nonatomic, readonly) BOOL isFullScreen; ///< 是否已全屏
6.6 是否正在旋轉(zhuǎn)
/// 如果為YES, 表示正在旋轉(zhuǎn)中
@property (nonatomic, readonly) BOOL isTransitioning;
6.7 當(dāng)前旋轉(zhuǎn)的方向
_player.rotationManager.currentOrientation
6.8 監(jiān)聽狀態(tài)改變??
///
/// 觀察者
///
/// 當(dāng)需要監(jiān)聽旋轉(zhuǎn)時(shí), 可以設(shè)置`player.rotationObserver.rotationDidStartExeBlock = ...;`
/// 了解更多請前往頭文件查看
///
@property (nonatomic, strong, readonly) id<SJRotationManagerObserver> rotationObserver;
6.9 自己動手?jǐn)]一個(gè) SJRotationManager, 替換作者原始實(shí)現(xiàn)
當(dāng)你想替換原始實(shí)現(xiàn)時(shí), 可以實(shí)現(xiàn) SJRotationManagerProtocol 中定義的方法.
7. 直接全屏而不旋轉(zhuǎn)
直接全屏, 或者說充滿屏幕, 但不旋轉(zhuǎn).
7.1 全屏和恢復(fù)
_player.fitOnScreen = YES;
[_player setFitOnScreen:NO animated:NO];
[_player setFitOnScreen:YES animated:YES completionHandler:^(__kindof SJBaseVideoPlayer * _Nonnull player) {
/// ...
}];
7.2 監(jiān)聽狀態(tài)改變??
@property (nonatomic, copy, nullable) void(^fitOnScreenWillBeginExeBlock)(__kindof SJBaseVideoPlayer *player);
@property (nonatomic, copy, nullable) void(^fitOnScreenDidEndExeBlock)(__kindof SJBaseVideoPlayer *player);;
7.3 是否是全屏
/// YES 為充滿屏幕
_player.isFitOnScreen
7.4 自己動手?jǐn)]一個(gè) SJFitOnScreenManager, 替換作者原始實(shí)現(xiàn)
該部分管理類的協(xié)議定義在 SJFitOnScreenManagerProtocol 中, 實(shí)現(xiàn)該協(xié)議的任何對象, 均可賦值給播放器, 替換原始實(shí)現(xiàn).
8. 鏡像翻轉(zhuǎn)
此部分內(nèi)容由 id<SJFlipTransitionManager> flipTransitionManager 提供支持
目前鏡像翻轉(zhuǎn)只寫了 水平翻轉(zhuǎn), 未來可能會加入更多的翻轉(zhuǎn)類型.
typedef enum : NSUInteger {
SJViewFlipTransition_Identity,
SJViewFlipTransition_Horizontally, // 水平翻轉(zhuǎn)
} SJViewFlipTransition;
8.1 翻轉(zhuǎn)和恢復(fù)
/// 當(dāng)前的翻轉(zhuǎn)類型
_player.flipTransition
/// 翻轉(zhuǎn)相關(guān)方法
[_player setFlipTransition:SJViewFlipTransition_Horizontally];
[_player setFlipTransition:SJViewFlipTransition_Horizontally animated:YES];
[_player setFlipTransition:SJViewFlipTransition_Identity animated:YES completionHandler:^(__kindof SJBaseVideoPlayer * _Nonnull player) {
/// ...
}];
8.2 監(jiān)聽狀態(tài)改變??
///
/// 觀察者
///
/// 可以如下設(shè)置block, 來監(jiān)聽某個(gè)狀態(tài)的改變
///
/// player.flipTransitionObserver.flipTransitionDidStartExeBlock = ...;
/// player.flipTransitionObserver.flipTransitionDidStopExeBlock = ...;
///
@property (nonatomic, strong, readonly) id<SJFlipTransitionManagerObserver> flipTransitionObserver;
8.3 自己動手?jǐn)]一個(gè) SJFlipTransitionManager, 替換作者原始實(shí)現(xiàn)
該部分管理類的協(xié)議定義在 SJFlipTransitionManagerProtocol 中, 實(shí)現(xiàn)該協(xié)議的任何對象, 均可賦值給播放器, 替換原始實(shí)現(xiàn).
9. 網(wǎng)絡(luò)狀態(tài)
此部分內(nèi)容由 id<SJReachability> reachability 提供支持
默認(rèn)的 reachability 是個(gè)單例, 在App生命周期中, 僅創(chuàng)建一次. 因此每個(gè)播放器對象持有的 reachability 都是相同的.
9.1 當(dāng)前的網(wǎng)絡(luò)狀態(tài)
@property (nonatomic, readonly) SJNetworkStatus networkStatus;
9.2 監(jiān)聽狀態(tài)改變??
///
/// 觀察者
///
@property (nonatomic, strong, readonly) id<SJReachabilityObserver> reachabilityObserver;
9.3 自己動手?jǐn)]一個(gè) SJReachability, 替換作者原始實(shí)現(xiàn)
該部分管理類的協(xié)議定義在 SJNetworkStatus 中, 實(shí)現(xiàn)該協(xié)議的任何對象, 均可賦值給播放器, 替換原始實(shí)現(xiàn).
10. 手勢
此部分內(nèi)容由 id<SJPlayerGestureControl> gestureControl 提供支持
播放器默認(rèn)存在四種手勢, 每個(gè)手勢觸發(fā)的回調(diào)均定義在 SJPlayerGestureControl 中, 當(dāng)想改變某個(gè)手勢的處理時(shí), 可以直接修改對應(yīng)手勢觸發(fā)的 block 即可.
具體請看以下部分.
10.1 單擊手勢
當(dāng)用戶單擊播放器時(shí), 播放器會調(diào)用 顯示或隱藏控制層的操作
以下為默認(rèn)實(shí)現(xiàn):
__weak typeof(self) _self = self;
_gestureControl.singleTapHandler = ^(id<SJPlayerGestureControl> _Nonnull control, CGPoint location) {
__strong typeof(_self) self = _self;
if ( !self ) return ;
/// 讓控制層顯示或隱藏
[self.controlLayerAppearManager switchAppearState];
};
10.2 雙擊手勢
雙擊會觸發(fā)暫?;虿シ诺牟僮?/p>
__weak typeof(self) _self = self;
_gestureControl.doubleTapHandler = ^(id<SJPlayerGestureControl> _Nonnull control, CGPoint location) {
__strong typeof(_self) self = _self;
if ( !self ) return ;
if ( [self playStatus_isPlaying] )
[self pause];
else
[self play];
};
10.3 移動手勢
- 垂直滑動時(shí), 默認(rèn)情況下如果在屏幕左邊, 則會觸發(fā)調(diào)整亮度的操作, 并顯示亮度提示視圖. 如果在屏幕右邊, 則會觸發(fā)調(diào)整聲音的操作, 并顯示系統(tǒng)音量提示視圖
- 水平滑動時(shí), 會觸發(fā)控制層相應(yīng)的代理方法
__weak typeof(self) _self = self;
_gestureControl.panHandler = ^(id<SJPlayerGestureControl> _Nonnull control, SJPanGestureTriggeredPosition position, SJPanGestureMovingDirection direction, SJPanGestureRecognizerState state, CGPoint translate) {
__strong typeof(_self) self = _self;
if ( !self ) return ;
/// ....
};
10.4 捏合手勢
當(dāng)用戶做放大或收縮觸發(fā)該手勢時(shí), 會設(shè)置播放器顯示模式Aspect或AspectFill.
__weak typeof(self) _self = self;
_gestureControl.pinchHandler = ^(id<SJPlayerGestureControl> _Nonnull control, CGFloat scale) {
__strong typeof(_self) self = _self;
if ( !self ) return ;
self.playbackController.videoGravity = scale > 1 ?AVLayerVideoGravityResizeAspectFill:AVLayerVideoGravityResizeAspect;
};
10.5 設(shè)置支持的手勢
_player.gestureControl.supportedGestureTypes = SJPlayerGestureTypeMask_All
typedef enum : NSUInteger {
SJPlayerGestureTypeMask_None,
SJPlayerGestureTypeMask_SingleTap = 1 << 0,
SJPlayerGestureTypeMask_DoubleTap = 1 << 1,
SJPlayerGestureTypeMask_Pan_H = 1 << 2, // 水平方向
SJPlayerGestureTypeMask_Pan_V = 1 << 3, // 垂直方向
SJPlayerGestureTypeMask_Pinch = 1 << 4,
SJPlayerGestureTypeMask_Pan = SJPlayerGestureTypeMask_Pan_H | SJPlayerGestureTypeMask_Pan_V,
SJPlayerGestureTypeMask_All = SJPlayerGestureTypeMask_SingleTap |
SJPlayerGestureTypeMask_DoubleTap |
SJPlayerGestureTypeMask_Pan |
SJPlayerGestureTypeMask_Pinch,
} SJPlayerGestureTypeMask;
10.6 自定義某個(gè)手勢的處理
/// 例如 替換單擊手勢的處理
__weak typeof(self) _self = self;
_player.gestureControl.singleTapHandler = ^(id<SJPlayerGestureControl> _Nonnull control, CGPoint location) {
__strong typeof(_self) self = _self;
if ( !self ) return ;
/// .....你的處理
};
11. 占位圖
資源在初始化時(shí), 由于暫時(shí)沒有畫面可以呈現(xiàn), 會出現(xiàn)短暫的黑屏. 在此期間, 建議大家設(shè)置一下占位圖.
11.1 設(shè)置本地占位圖
_player.presentView.placeholderImageView.image = [UIImage imageNamed:@"..."];
11.2 設(shè)置網(wǎng)絡(luò)占位圖
[_player.presentView.placeholderImageView sd_setImageWithURL:URL placeholderImage:img];
11.3 是否隱藏占位圖 - 播放器準(zhǔn)備好顯示時(shí)
/// 播放器準(zhǔn)備好顯示時(shí), 是否隱藏占位圖
/// - 默認(rèn)為YES
@property (nonatomic) BOOL hiddenPlaceholderImageViewWhenPlayerIsReadyForDisplay;
12. 顯示提示文本
目前僅支持 NSAttributedString.
12.1 顯示管理類
///
/// 中心彈出文本提示
///
/// 了解更多請前往協(xié)議頭文件查看
///
@property (nonatomic, strong, null_resettable) id<SJPromptProtocol> prompt;
///
/// 右下角彈出提示
///
/// 了解更多請前往協(xié)議頭文件查看
///
@property (nonatomic, strong, null_resettable) id<SJPopPromptControllerProtocol> popPromptController;
12.2 配置提示文本
_player.prompt.backgroundColor = ...;
_player.prompt.contentInset = ...;
13. 一些固定代碼
接入播放器的 ViewController 中, 會寫一些固定的代碼, 我將這些固定代碼(例如 進(jìn)入下個(gè)頁面時(shí), 需要當(dāng)前頁面的播放器暫停), 都封裝在了以下方法中.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[_player vc_viewDidAppear];
}
在適當(dāng)?shù)臅r(shí)候直接調(diào)用即可, 以下為內(nèi)部實(shí)現(xiàn):
13.1 - (void)vc_viewDidAppear;
當(dāng) ViewController 的 viewDidAppear 調(diào)用時(shí), 恢復(fù)播放
實(shí)現(xiàn)如下:
- (void)vc_viewDidAppear {
if ( !self.isPlayOnScrollView || (self.isPlayOnScrollView && self.isScrollAppeared) ) {
/// 恢復(fù)播放
[self play];
}
/// 標(biāo)識vc已顯示
/// vc_isDisappeared 是自動旋轉(zhuǎn)觸發(fā)的條件之一, 如果控制器 disappear 了, 就不會觸發(fā)旋轉(zhuǎn)
self.vc_isDisappeared = NO;
}
13.2 - (void)vc_viewWillDisappear;
當(dāng) ViewController 的 viewWillDisappear 調(diào)用時(shí), 設(shè)置標(biāo)識為YES
實(shí)現(xiàn)如下:
- (void)vc_viewWillDisappear {
/// 標(biāo)識vc已顯示
/// vc_isDisappeared 是自動旋轉(zhuǎn)觸發(fā)的條件之一, 如果控制器 disappear 了, 就不會觸發(fā)旋轉(zhuǎn)
self.vc_isDisappeared = YES;
}
13.3 - (void)vc_viewDidDisappear;
當(dāng) ViewController 的 viewDidDisappear 調(diào)用時(shí), 暫停播放
實(shí)現(xiàn)如下:
- (void)vc_viewDidDisappear {
[self pause];
}
13.4 - (BOOL)vc_prefersStatusBarHidden;
狀態(tài)欄是否可以隱藏
實(shí)現(xiàn)如下:
- (BOOL)vc_prefersStatusBarHidden {
if ( _tmpShowStatusBar ) return NO; // 臨時(shí)顯示
if ( _tmpHiddenStatusBar ) return YES; // 臨時(shí)隱藏
if ( self.lockedScreen ) return YES; // 鎖屏?xí)r, 不顯示
if ( self.rotationManager.isTransitioning ) { // 旋轉(zhuǎn)時(shí), 不顯示
if ( !self.disabledControlLayerAppearManager && self.isControlLayerAppeared ) return NO;
return YES;
}
// 全屏播放時(shí), 使?fàn)顟B(tài)欄根據(jù)控制層顯示或隱藏
if ( self.isFullScreen ) return !self.isControlLayerAppeared;
return NO;
}
13.5 - (UIStatusBarStyle)vc_preferredStatusBarStyle;
狀態(tài)欄顯示白色還是黑色
實(shí)現(xiàn)如下:
- (UIStatusBarStyle)vc_preferredStatusBarStyle {
// 全屏播放時(shí), 使?fàn)顟B(tài)欄變成白色
if ( self.isFullScreen || self.fitOnScreen ) return UIStatusBarStyleLightContent;
return UIStatusBarStyleDefault;
}
13.6 - 臨時(shí)顯示狀態(tài)欄
有時(shí)候, 可能會希望臨時(shí)顯示狀態(tài)欄, 例如全屏轉(zhuǎn)回小屏?xí)r, 旋轉(zhuǎn)之前, 需要將狀態(tài)欄顯示.
[_player needShowStatusBar];
13.7 - 臨時(shí)隱藏狀態(tài)欄
有時(shí)候, 可能會希望臨時(shí)隱藏狀態(tài)欄, 例如某個(gè)播放器控制層不需要顯示狀態(tài)欄.
[_player needHiddenStatusBar];
14. 截屏
14.1 當(dāng)前時(shí)間截圖
UIImage *img = [_player screenshot];
14.2 指定時(shí)間截圖
- (void)screenshotWithTime:(NSTimeInterval)secs
completion:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, UIImage * __nullable image, NSError *__nullable error))block;
/// 可以通過 _player.playbackController.presentationSize 來獲取當(dāng)前視頻寬高
- (void)screenshotWithTime:(NSTimeInterval)secs
size:(CGSize)size
completion:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, UIImage * __nullable image, NSError *__nullable error))block;
15. 導(dǎo)出視頻或GIF
15.1 導(dǎo)出視頻
- (void)exportWithBeginTime:(NSTimeInterval)beginTime
duration:(NSTimeInterval)duration
presetName:(nullable NSString *)presetName
progress:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, float progress))progressBlock
completion:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, NSURL *fileURL, UIImage *thumbnailImage))completion
failure:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, NSError *error))failure;
15.2 導(dǎo)出GIF
- (void)generateGIFWithBeginTime:(NSTimeInterval)beginTime
duration:(NSTimeInterval)duration
progress:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, float progress))progressBlock
completion:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, UIImage *imageGIF, UIImage *thumbnailImage, NSURL *filePath))completion
failure:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, NSError *error))failure;
15.3 取消操作
/// 取消導(dǎo)出操作
/// 播放器 dealloc 時(shí), 會調(diào)用一次
- (void)cancelExportOperation;
/// 取消GIF操作
/// 播放器 dealloc 時(shí), 會調(diào)用一次
- (void)cancelGenerateGIFOperation;
16. 滾動相關(guān)
此部分的內(nèi)容由 SJPlayModelPropertiesObserver 提供支持.
16.1 是否在 UICollectionView 或者 UITableView 中播放
/// 是否是在 UICollectionView 或者 UITableView 中播放
_player.isPlayOnScrollView
16.2 是否已顯示
///
/// 播放器視圖是否顯示
///
/// Whether the player is appeared when playing on scrollView. Because scrollview may be scrolled.
///
@property (nonatomic, readonly) BOOL isScrollAppeared;
16.3 播放器視圖將要滾動顯示和消失的回調(diào)
@property (nonatomic, copy, nullable) void(^playerViewWillAppearExeBlock)(__kindof SJBaseVideoPlayer *videoPlayer);
@property (nonatomic, copy, nullable) void(^playerViewWillDisappearExeBlock)(__kindof SJBaseVideoPlayer *videoPlayer);
16.4 滾動出去后, 是否暫停
///
/// 滾動出去后, 是否暫停. 默認(rèn)為YES
///
/// - default value is YES.
///
@property (nonatomic) BOOL pauseWhenScrollDisappeared;
16.5 滾動進(jìn)入時(shí), 是否恢復(fù)播放
///
/// 滾動進(jìn)入時(shí), 是否恢復(fù)播放. 默認(rèn)為YES
///
/// - default values is YES.
///
@property (nonatomic) BOOL resumePlaybackWhenScrollAppeared;
16.6 滾動出去后, 是否隱藏播放器視圖
///
/// 滾動出去后, 是否隱藏播放器視圖. 默認(rèn)為YES
///
/// - default value is YES.
///
@property (nonatomic) BOOL hiddenViewWhenScrollDisappeared;
17. 自動播放 - 在 UICollectionView 或者 UITableView 中
目前支持在 UICollectionViewCell 和 UITableViewCell 中自動播放.
使用之前, 請導(dǎo)入頭文件 #import "UIScrollView+ListViewAutoplaySJAdd.h"
17.1 開啟
/// 配置列表自動播放
[_tableView sj_enableAutoplayWithConfig:[SJPlayerAutoplayConfig configWithPlayerSuperviewTag:101 autoplayDelegate:self]];
/// Delegate method
- (void)sj_playerNeedPlayNewAssetAtIndexPath:(NSIndexPath *)indexPath {
}
17.2 配置
typedef NS_ENUM(NSUInteger, SJAutoplayScrollAnimationType) {
SJAutoplayScrollAnimationTypeNone,
SJAutoplayScrollAnimationTypeTop,
SJAutoplayScrollAnimationTypeMiddle,
};
@interface SJPlayerAutoplayConfig : NSObject
+ (instancetype)configWithPlayerSuperviewTag:(NSInteger)playerSuperviewTag
autoplayDelegate:(id<SJPlayerAutoplayDelegate>)autoplayDelegate;
/// 滾動的動畫類型
/// default is .Middle;
@property (nonatomic) SJAutoplayScrollAnimationType animationType;
@property (nonatomic, readonly) NSInteger playerSuperviewTag;
@property (nonatomic, weak, nullable, readonly) id<SJPlayerAutoplayDelegate> autoplayDelegate;
@end
@protocol SJPlayerAutoplayDelegate <NSObject>
- (void)sj_playerNeedPlayNewAssetAtIndexPath:(NSIndexPath *)indexPath;
@end
17.3 關(guān)閉
[_tableView sj_disenableAutoplay];
17.4 主動調(diào)用播放下一個(gè)資源
[_tableView sj_needPlayNextAsset];
18. 對控制層上面的Item的操作
18.1 添加
SJEdgeControlButtonItem *item = [[SJEdgeControlButtonItem alloc] initWithImage:[UIImage imageNamed:@"test"] target:self action:@selector(test) tag:SJTestImageItemTag];
[_player.defaultEdgeControlLayer.topAdapter addItem:item];
[_player.defaultEdgeControlLayer.topAdapter reload];
18.2 刪除
[_player.defaultEdgeControlLayer.bottomAdapter removeItemForTag:SJEdgeControlLayerBottomItem_Separator];
[_player.defaultEdgeControlLayer.bottomAdapter reload];
18.3 調(diào)整位置
[_player.defaultEdgeControlLayer.bottomAdapter exchangeItemForTag:SJEdgeControlLayerBottomItem_DurationTime withItemForTag:SJEdgeControlLayerBottomItem_Progress];
[_player.defaultEdgeControlLayer.bottomAdapter reload];
19. 對控制層上的Item的一些補(bǔ)充
19.1 設(shè)置與前后item的間距
SJEdgeControlButtonItem *titleItem = [_player.defaultEdgeControlLayer.topAdapter itemForTag:SJEdgeControlLayerTopItem_Title];
titleItem.insets = SJEdgeInsetsMake(16, 16);
[_player.defaultEdgeControlLayer.topAdapter reload];
19.2 設(shè)置隱藏
SJEdgeControlButtonItem *titleItem = [_player.defaultEdgeControlLayer.topAdapter itemForTag:SJEdgeControlLayerTopItem_Title];
titleItem.hidden = YES;
[_player.defaultEdgeControlLayer.topAdapter reload];
19.3 填充剩余空間
SJEdgeControlButtonItem *titleItem = [_player.defaultEdgeControlLayer.topAdapter itemForTag:SJEdgeControlLayerTopItem_Title];
titleItem.fill = YES;
[_player.defaultEdgeControlLayer.topAdapter reload];
20. SJEdgeControlLayer 的補(bǔ)充
20.1 是否豎屏?xí)r隱藏返回按鈕
_player.defaultEdgeControlLayer.hiddenBackButtonWhenOrientationIsPortrait = YES;
20.2 是否禁止網(wǎng)絡(luò)狀態(tài)變化提示
_player.defaultEdgeControlLayer.disabledPromptWhenNetworkStatusChanges = YES;
20.3 是否使返回按鈕常駐
_player.defaultEdgeControlLayer.showResidentBackButton = YES;
20.4 是否隱藏底部進(jìn)度條
_player.defaultEdgeControlLayer.hiddenBottomProgressIndicator = YES;
20.5 是否在loadingView上顯示網(wǎng)速
_player.defaultEdgeControlLayer.showNetworkSpeedToLoadingView = YES;
20.6 自定義loadingView
// 實(shí)現(xiàn)協(xié)議`SJEdgeControlLayerLoadingViewProtocol`即可, 然后賦值給控制層
_player.defaultEdgeControlLayer.loadingView = Your Loading View;
20.7 調(diào)整邊距
_player.defaultEdgeControlLayer.leftMargin = 16;
_player.defaultEdgeControlLayer.rightMargin = 16;
20.8 取消控制層上下視圖的陰影
[_player.defaultEdgeControlLayer.topContainerView cleanColors];
[_player.defaultEdgeControlLayer.bottomContainerView cleanColors];