Create your Gitee Account
Explore and code with more than 5 million developers,Free private repositories !:)
Sign up
Clone or download
Cancel
Notice: Creating folder will generate an empty file .keep, because not support in Git
Loading...
README.md

readme

Build Status Version Platform License

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.
pod 'SJBaseVideoPlayer'

天朝

# 如果网络不行安装不了, 可改成以下方式进行安装
pod 'SJBaseVideoPlayer', :git => 'https://gitee.com/changsanjiang/SJBaseVideoPlayer.git'
pod 'SJVideoPlayer', :git => 'https://gitee.com/changsanjiang/SJVideoPlayer.git'
$ pod update --no-repo-update   (不要用 pod install , 用这个命令安装)

Wiki

Welcome to the SJVideoPlayer wiki!

Author

Email: changsanjiang@gmail.com

QQGroup: 930508201 (iOS 开发)

请我喝咖啡☕️

Documents

v2.6.5 往后的版本, 请配置旋转 !!

1. 视图层次结构

该部分内容已迁移至wiki

2. URLAsset

3. 播放控制

4. 控制层的显示和隐藏

5. 设备亮度和音量

6. 旋转

内容已经迁移至Wiki

7. 直接全屏而不旋转

内容已经迁移至Wiki

8. 镜像翻转

9. 网络状态

10. 手势

11. 占位图

12. 显示提示文本

13. 一些固定代码

14. 截屏

15. 导出视频或GIF

16. 滚动相关

17. 自动播放 - 在 UICollectionView 或者 UITableView 中

18. 对控制层上的Item的操作

19. 对控制层上的Item的一些补充

20. SJEdgeControlLayer 的补充


以下为详细介绍:

2. URLAsset

播放器 播放的资源是通过 SJVideoPlayerURLAsset 创建的. SJVideoPlayerURLAsset 由两部分组成:

视图层次 (第一部分中的SJPlayModel) 资源地址 (可以是本地资源/URL/AVAsset)

默认情况下, 创建了 SJVideoPlayerURLAsset , 赋值给播放器后即可播放.


2.1 播放 URL(本地文件或远程资源)

NSURL *URL = [NSURL URLWithString:@"https://...example.mp4"];
_player.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithURL:URL];

2.2 播放 AVAsset 或其子类

_player.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithAVAsset:avAsset];

2.3 从指定的位置开始播放

NSTimeInterval secs = 20.0;
_player.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithURL:URL startPosition:secs]; // 直接从20秒处开始播放

2.4 续播(进入下个页面时, 继续播放)

我们可能需要切换界面时, 希望视频能够在下一个界面无缝的进行播放. 使用如下方法, 传入正在播放的资源, 将新的资源赋值给播放器播放即可.

// otherAsset 即为上一个页面播放的Asset
// 除了需要一个otherAsset, 其他方面同以上的示例一模一样
_player.URLAsset = [SJVideoPlayerURLAsset.alloc initWithOtherAsset:otherAsset]; 

2.5 播放记录

内容已迁移至wiki: https://github.com/changsanjiang/SJVideoPlayer/wiki/%E6%92%AD%E6%94%BE%E8%AE%B0%E5%BD%95


3. 播放控制

播放控制: 对播放进行的操作. 此部分的内容由 "id <SJMediaPlaybackController> playbackController" 提供支持.

大多数对播放进行的操作, 均在协议 SJMediaPlaybackController 进行了声明.

正常来说实现了此协议的任何对象, 均可赋值给 player.playbackController 来替换原始实现.

3.1 播放

[_player play];

3.2 暂停

[_player pause];

3.3 刷新

在播放一个资源时, 可能有一些意外情况导致播放失败(如网络环境差).

此时当用户点击刷新按钮, 我们需要对当前的资源(Asset)进行刷新.

SJBaseVideoPlayer提供了直接的方法去刷新, 不需要开发者再重复的去创建新的Asset.

[_player refresh];

3.4 重播

从头开始重新播放

[_player replay];

3.5 停止

停止播放, 请注意: 当前资源将会被清空, 如需重播, 请重新设置新资源

[_player stop];

3.6 静音

_player.muted = YES;

3.7 调速

// 默认值为 1.0
_player.rate = 1.0;

3.8 报错

当播放发生错误时, 可以通过它来获取错误信息

_player.error

3.9 跳转

///
/// 是否精确跳转, default value is NO.
///
@property (nonatomic) BOOL accurateSeeking;

///
/// 跳转到指定位置播放
///
- (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 切换清晰度

///
/// 切换清晰度
///
- (void)switchVideoDefinition:(SJVideoPlayerURLAsset *)URLAsset;

///
/// 当前清晰度切换的信息
///
@property (nonatomic, strong, readonly) SJVideoDefinitionSwitchingInfo *definitionSwitchingInfo;

/// 以下为设置 SJVideoPlayer.definitionURLAssets, 将会在清晰度切换控制层中显示这些资源项. 

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 将会在用户选择后进行切换)
_player.URLAsset = asset1;

3.11 当前时间

@property (nonatomic, readonly) NSTimeInterval currentTime;                         ///< 当前播放到的时间

3.12 总时长

@property (nonatomic, readonly) NSTimeInterval duration;                            ///< 总时长

3.13 缓冲时长

@property (nonatomic, readonly) NSTimeInterval playableDuration;                    ///< 缓冲到的时间

3.14 是否已播放完毕

@property (nonatomic, readonly) BOOL isPlaybackFinished;                            ///< 当前资源是否已播放结束

3.15 是否调用过播放

@property (nonatomic, readonly) BOOL isPlayed;                                      ///< 是否播放过当前的资源

3.16 是否调用过重播

@property (nonatomic, readonly) BOOL isReplayed;                                    ///< 是否重播过当前的资源

3.17 设置新资源时, 是否自动播放

@property (nonatomic) BOOL autoplayWhenSetNewAsset;                    ///< 设置新的资源后, 是否自动调用播放. 默认为 YES

3.18 进入后台, 是否暂停播放

关于后台播放视频, 引用自: https://juejin.im/post/5a38e1a0f265da4327185a26

当您想在后台播放视频时:

  1. 需要设置 videoPlayer.pauseWhenAppDidEnterBackground = NO; (该值默认为YES, 即App进入后台默认暂停).

  2. 前往 TARGETS -> Capability -> enable Background Modes -> select this mode Audio, AirPlay, and Picture in Picture

_player.pauseWhenAppDidEnterBackground = NO; // 默认值为 YES, 即进入后台后 暂停.

3.19 进入前台, 是否恢复播放

@property (nonatomic) BOOL resumePlaybackWhenAppDidEnterForeground;    ///< 进入前台时, 是否恢复播放. 默认为 NO

3.20 跳转完成, 是否恢复播放

@property (nonatomic) BOOL resumePlaybackWhenPlayerHasFinishedSeeking; ///< 当`seekToTime:`操作完成后, 是否恢复播放. 默认为 YES

3.21 资源准备状态

资源准备(或初始化)的状态

当未设置资源时, 此时 player.assetStatus = .unknown 当设置新资源时, 此时 player.assetStatus = .preparing 当准备好播放时, 此时 player.assetStatus = .readyToPlay 当初始化失败时, 此时 player.assetStatus = .failed

typedef NS_ENUM(NSInteger, SJAssetStatus) {
///
/// 未知状态
///
SJAssetStatusUnknown,

///
/// 准备中
///
SJAssetStatusPreparing,

///
/// 当前资源可随时进行播放(播放控制请查看`timeControlStatus`)
///
SJAssetStatusReadyToPlay,

///
/// 发生错误
///
SJAssetStatusFailed
};

3.22 播放控制状态

暂停或播放的控制状态

当调用了暂停时, 此时 player.timeControlStatus = .paused

当调用了播放时, 此时 将可能处于以下两种状态中的任意一个:

  • player.timeControlStatus = .playing 正在播放中.

  • player.timeControlStatus = .waitingToPlay 等待播放, 等待的原因请查看 player.reasonForWaitingToPlay

typedef NS_ENUM(NSInteger, SJPlaybackTimeControlStatus) {
///
/// 暂停状态(已调用暂停或未执行任何操作的状态)
///
SJPlaybackTimeControlStatusPaused,

///
/// 播放状态(已调用播放), 当前正在缓冲或正在评估能否播放. 可以通过`reasonForWaitingToPlay`来获取原因, UI层可以根据原因来控制loading视图的状态.
///
SJPlaybackTimeControlStatusWaitingToPlay,

///
/// 播放状态(已调用播放), 当前播放器正在播放
///
SJPlaybackTimeControlStatusPlaying
};

3.23 播放等待的原因

当调用了播放, 播放器未能播放处于等待状态时的原因

等待原因有以下3种状态: 1.未设置资源, 此时设置资源后, 当player.assetStatus = .readyToPlay, 播放器将自动进行播放. 2.可能是由于缓冲不足, 播放器在等待缓存足够时自动恢复播放, 此时可以显示loading视图. 3.可能是正在评估缓冲中, 这个过程会进行的很快, 不需要显示loading视图.

///
/// 缓冲中, UI层建议显示loading视图 
///
extern SJWaitingReason const SJWaitingToMinimizeStallsReason;

///
/// 正在评估能否播放, 处于此状态时, 不建议UI层显示loading视图
///
extern SJWaitingReason const SJWaitingWhileEvaluatingBufferingRateReason;

///
/// 未设置资源
///
extern SJWaitingReason const SJWaitingWithNoAssetToPlayReason;

3.24 监听状态改变🔥

///
/// 观察者
///
///         可以如下设置block, 来监听某个状态的改变
///         了解更多请前往头文件查看
///         player.playbackObserver.currentTimeDidChangeExeBlock = ...;
///         player.playbackObserver.durationDidChangeExeBlock = ...;
///         player.playbackObserver.timeControlStatusDidChangeExeBlock = ...;
///
@property (nonatomic, strong, readonly) SJPlaybackObservation *playbackObserver;

3.25 已观看的时长(当前资源)

@property (nonatomic, readonly) NSTimeInterval durationWatched;                     ///< 已观看的时长(当前资源)

3.26 接入别的视频 SDK, 自己动手撸一个 SJVideoPlayerPlaybackController, 替换作者原始实现

某些时候, 我们需要接入第三方的视频SDK, 但是又想使用 SJBaseVideoPlayer 封装的其他的功能.

这个时候, 我们可以自己动手, 将第三方的SDK封装一下, 实现 SJVideoPlayerPlaybackController 协议, 管理 SJBaseVideoPlayer 中的播放操作.

示例:

_player.playbackController = Your PlaybackController.

4. 控制层的显示和隐藏

控制层的显示和隐藏, 此部分的内容由 "id <SJControlLayerAppearManager> controlLayerAppearManager" 提供支持.

controlLayerAppearManager 内部存在一个定时器, 当控制层显示时, 会开启此定时器. 一定间隔后, 会尝试隐藏控制层.

其他相关操作, 请见以下内容.

4.1 让控制层显示

当控制层需要显示时, 可以调用下面方法.

[_player controlLayerNeedAppear];

此方法将会回调控制层的代理方法:

"- (void)controlLayerNeedAppear:(__kindof SJBaseVideoPlayer *)videoPlayer;"

代理将会对当前的控制层进行显示处理.

4.2 让控制层隐藏

当控制层需要隐藏时, 可以调用下面方法.

[_player controlLayerNeedDisappear];

此方法将会回调控制层的代理方法:

"- (void)controlLayerNeedDisappear:(__kindof SJBaseVideoPlayer *)videoPlayer;"

代理将会对当前的控制层进行隐藏处理.

4.3 控制层是否显示中

///
/// 控制层的显示状态(是否已显示)
///
@property (nonatomic, getter=isControlLayerAppeared) BOOL controlLayerAppeared;

4.4 是否在暂停时保持控制层显示

///
/// 暂停的时候是否保持控制层显示
///
///         default value is NO
///
@property (nonatomic) BOOL pausedToKeepAppearState;

4.5 监听状态改变🔥

///
/// 观察者
///
///         当需要监听控制层的显示和隐藏时, 可以设置`player.controlLayerAppearObserver.appearStateDidChangeExeBlock = ...;`
///
@property (nonatomic, strong, readonly) id<SJControlLayerAppearManagerObserver> controlLayerAppearObserver;

4.6 自己动手撸一个 SJControlLayerAppearManager, 替换作者原始实现

同样的, 协议 "SJControlLayerAppearManager" 定义了一系列的操作, 只要实现了这些协议方法的对象, 就可以管理控制层的显示和隐藏.

_player.controlLayerAppearManager = Your controlLayerAppearManager; 

5. 设备亮度和音量

设备亮度和音量的调整, 此部分的内容由 "id <SJDeviceVolumeAndBrightnessManager> deviceVolumeAndBrightnessManager" 提供支持.

5.1 调整设备亮度
// 0 到 1
_player.deviceVolumeAndBrightnessManager.brightness = 1.0;

5.2 调整设备声音
// 0 到 1
_player.deviceVolumeAndBrightnessManager.volume = 1.0;

5.3 监听状态改变🔥
///
/// 观察者
///
@property (nonatomic, strong, readonly) id<SJDeviceVolumeAndBrightnessManagerObserver> deviceVolumeAndBrightnessObserver;

5.4 禁止播放器设置
_player.disableBrightnessSetting = YES;
_player.disableVolumeSetting = YES;

5.5 自己动手撸一个 SJDeviceVolumeAndBrightnessManager, 替换作者原始实现

当需要对设备音量视图进行自定义时, 可以自己动手撸一个 SJDeviceVolumeAndBrightnessManager.

_player.deviceVolumeAndBrightnessManager = Your deviceVolumeAndBrightnessManager;

8. 镜像翻转

此部分内容由 id<SJFlipTransitionManager> flipTransitionManager 提供支持

目前镜像翻转只写了 水平翻转, 未来可能会加入更多的翻转类型.

typedef enum : NSUInteger {
SJViewFlipTransition_Identity,
SJViewFlipTransition_Horizontally, // 水平翻转
} SJViewFlipTransition;

8.1 翻转和恢复

/// 当前的翻转类型
_player.flipTransition

/// 翻转相关方法
[_player setFlipTransition:SJViewFlipTransition_Horizontally];
[_player setFlipTransition:SJViewFlipTransition_Horizontally animated:YES];
[_player setFlipTransition:SJViewFlipTransition_Identity animated:YES completionHandler:^(__kindof SJBaseVideoPlayer * _Nonnull player) {
/// ...
}];

8.2 监听状态改变🔥

///
/// 观察者
///
///         可以如下设置block, 来监听某个状态的改变
///
///         player.flipTransitionObserver.flipTransitionDidStartExeBlock = ...;
///         player.flipTransitionObserver.flipTransitionDidStopExeBlock = ...;
///
@property (nonatomic, strong, readonly) id<SJFlipTransitionManagerObserver> flipTransitionObserver;

8.3 自己动手撸一个 SJFlipTransitionManager, 替换作者原始实现

该部分管理类的协议定义在 SJFlipTransitionManagerProtocol 中, 实现该协议的任何对象, 均可赋值给播放器, 替换原始实现.


9. 网络状态

此部分内容由 id<SJReachability> reachability 提供支持

默认的 reachability 是个单例, 在App生命周期中, 仅创建一次. 因此每个播放器对象持有的 reachability 都是相同的.

9.1 当前的网络状态

@property (nonatomic, readonly) SJNetworkStatus networkStatus;

9.2 监听状态改变🔥

///
/// 观察者
///
@property (nonatomic, strong, readonly) id<SJReachabilityObserver> reachabilityObserver;

9.3 自己动手撸一个 SJReachability, 替换作者原始实现

该部分管理类的协议定义在 SJNetworkStatus 中, 实现该协议的任何对象, 均可赋值给播放器, 替换原始实现.


10. 手势

此部分内容由 id<SJPlayerGestureControl> gestureControl 提供支持

播放器默认存在四种手势, 每个手势触发的回调均定义在 SJPlayerGestureControl 中, 当想改变某个手势的处理时, 可以直接修改对应手势触发的 block 即可.

具体请看以下部分.

10.1 单击手势

当用户单击播放器时, 播放器会调用 显示或隐藏控制层的操作

以下为默认实现:

__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 双击手势

双击会触发暂停或播放的操作

__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 移动手势

  • 垂直滑动时, 默认情况下如果在屏幕左边, 则会触发调整亮度的操作, 并显示亮度提示视图. 如果在屏幕右边, 则会触发调整声音的操作, 并显示系统音量提示视图
  • 水平滑动时, 会触发控制层相应的代理方法
__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 捏合手势

当用户做放大或收缩触发该手势时, 会设置播放器显示模式`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 设置支持的手势

_player.gestureControl.supportedGestureTypes = SJPlayerGestureTypeMask_Default

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_LongPress   = 1 << 5,
    
    SJPlayerGestureTypeMask_Pan = SJPlayerGestureTypeMask_Pan_H | SJPlayerGestureTypeMask_Pan_V,
    SJPlayerGestureTypeMask_Default = SJPlayerGestureTypeMask_SingleTap | SJPlayerGestureTypeMask_DoubleTap | SJPlayerGestureTypeMask_Pan | SJPlayerGestureTypeMask_Pinch,
    SJPlayerGestureTypeMask_All = SJPlayerGestureTypeMask_Default | SJPlayerGestureTypeMask_LongPress,
} SJPlayerGestureTypeMask;

10.6 自定义某个手势的处理

/// 例如 替换单击手势的处理
__weak typeof(self) _self = self;
_player.gestureControl.singleTapHandler = ^(id<SJPlayerGestureControl>  _Nonnull control, CGPoint location) {
__strong typeof(_self) self = _self;
if ( !self ) return ;
/// .....你的处理
};

11. 占位图

资源在初始化时, 由于暂时没有画面可以呈现, 会出现短暂的黑屏. 在此期间, 建议大家设置一下占位图.

11.1 设置本地占位图

_player.presentView.placeholderImageView.image = [UIImage imageNamed:@"..."];

11.2 设置网络占位图

[_player.presentView.placeholderImageView sd_setImageWithURL:URL placeholderImage:img];

11.3 是否隐藏占位图 - 播放器准备好显示时

/// 播放器准备好显示时, 是否隐藏占位图
/// - 默认为YES
@property (nonatomic) BOOL hiddenPlaceholderImageViewWhenPlayerIsReadyForDisplay;

12. 显示提示文本

目前仅支持 NSAttributedString.

12.1 显示管理类

///
/// 中心弹出文本提示
///
///         了解更多请前往协议头文件查看
///
@property (nonatomic, strong, null_resettable) id<SJPromptProtocol> prompt;

///
/// 左下角弹出提示
///
///         了解更多请前往协议头文件查看
///
@property (nonatomic, strong, null_resettable) id<SJPopPromptController> popPromptController;

12.2 配置提示文本

_player.prompt.backgroundColor = ...;
_player.prompt.contentInset = ...;

13. 一些固定代码

接入播放器的 ViewController 中, 会写一些固定的代码, 我将这些固定代码都封装在了以下方法中.

在适当的时候直接调用即可, 以下为内部实现:

13.4 - (BOOL)vc_prefersStatusBarHidden;

状态栏是否可以隐藏

实现如下:

- (BOOL)vc_prefersStatusBarHidden {
if ( _tmpShowStatusBar ) return NO;         // 临时显示
if ( _tmpHiddenStatusBar ) return YES;      // 临时隐藏
if ( self.lockedScreen ) return YES;        // 锁屏时, 不显示
if ( self.rotationManager.isTransitioning ) { // 旋转时, 不显示
if ( !self.disabledControlLayerAppearManager && self.isControlLayerAppeared ) return NO;
return YES;
}
// 全屏播放时, 使状态栏根据控制层显示或隐藏
if ( self.isFullScreen ) return !self.isControlLayerAppeared;
return NO;
}

13.5 - (UIStatusBarStyle)vc_preferredStatusBarStyle;

状态栏显示白色还是黑色

实现如下:

- (UIStatusBarStyle)vc_preferredStatusBarStyle {
// 全屏播放时, 使状态栏变成白色
if ( self.isFullScreen || self.fitOnScreen ) return UIStatusBarStyleLightContent;
return UIStatusBarStyleDefault;
}

13.6 - 临时显示状态栏

有时候, 可能会希望临时显示状态栏, 例如全屏转回小屏时, 旋转之前, 需要将状态栏显示.

[_player needShowStatusBar]; 

13.7 - 临时隐藏状态栏

有时候, 可能会希望临时隐藏状态栏, 例如某个播放器控制层不需要显示状态栏.

[_player needHiddenStatusBar]; 

14. 截屏

14.1 当前时间截图

UIImage *img = [_player screenshot];

14.2 指定时间截图

- (void)screenshotWithTime:(NSTimeInterval)secs
completion:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, UIImage * __nullable image, NSError *__nullable error))block;

/// 可以通过 _player.playbackController.presentationSize 来获取当前视频宽高
- (void)screenshotWithTime:(NSTimeInterval)secs
size:(CGSize)size
completion:(void(^)(__kindof SJBaseVideoPlayer *videoPlayer, UIImage * __nullable image, NSError *__nullable error))block;

15. 导出视频或GIF

15.1 导出视频

- (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 导出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 取消操作

/// 取消导出操作
/// 播放器 dealloc 时, 会调用一次 
- (void)cancelExportOperation;

/// 取消GIF操作
/// 播放器 dealloc 时, 会调用一次 
- (void)cancelGenerateGIFOperation;

16. 滚动相关

此部分的内容由 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 播放器视图将要滚动显示和消失的回调

@property (nonatomic, copy, nullable) void(^playerViewWillAppearExeBlock)(__kindof SJBaseVideoPlayer *videoPlayer);
@property (nonatomic, copy, nullable) void(^playerViewWillDisappearExeBlock)(__kindof SJBaseVideoPlayer *videoPlayer);

16.4 滚动出去后, 是否暂停

///
/// 滚动出去后, 是否暂停. 默认为YES
///
/// - default value is YES.
///
@property (nonatomic) BOOL pauseWhenScrollDisappeared;

16.5 滚动进入时, 是否恢复播放

///
/// 滚动进入时, 是否恢复播放. 默认为YES
///
/// - default values is YES.
///
@property (nonatomic) BOOL resumePlaybackWhenScrollAppeared;

16.6 滚动出去后, 是否隐藏播放器视图

///
/// 滚动出去后, 是否隐藏播放器视图. 默认为YES
///
/// - default value is YES.
///
@property (nonatomic) BOOL hiddenViewWhenScrollDisappeared;

17. 自动播放 - 在 UICollectionView 或者 UITableView 中

目前支持在 UICollectionViewCell 和 UITableViewCell 中自动播放.

使用之前, 请导入头文件 #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 关闭

[_tableView sj_disenableAutoplay];

17.4 主动调用播放下一个资源

[_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 调整位置

[_player.defaultEdgeControlLayer.bottomAdapter exchangeItemForTag:SJEdgeControlLayerBottomItem_DurationTime withItemForTag:SJEdgeControlLayerBottomItem_Progress];
[_player.defaultEdgeControlLayer.bottomAdapter reload];

19. 对控制层上的Item的一些补充

19.1 设置与前后item的间距

SJEdgeControlButtonItem *titleItem = [_player.defaultEdgeControlLayer.topAdapter itemForTag:SJEdgeControlLayerTopItem_Title];
titleItem.insets = SJEdgeInsetsMake(16, 16);
[_player.defaultEdgeControlLayer.topAdapter reload];

19.2 设置隐藏

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 的补充

20.1 是否竖屏时隐藏返回按钮

_player.defaultEdgeControlLayer.hiddenBackButtonWhenOrientationIsPortrait = YES;

20.2 是否禁止网络状态变化提示

_player.defaultEdgeControlLayer.disabledPromptWhenNetworkStatusChanges = YES;

20.3 是否使返回按钮常驻

_player.defaultEdgeControlLayer.showResidentBackButton = YES;

20.4 是否隐藏底部进度条

_player.defaultEdgeControlLayer.hiddenBottomProgressIndicator = YES;

20.5 是否在loadingView上显示网速

_player.defaultEdgeControlLayer.showNetworkSpeedToLoadingView = YES;

20.6 自定义loadingView

// 实现协议`SJLoadingView`即可, 然后赋值给控制层
_player.defaultEdgeControlLayer.loadingView = Your Loading View;

20.7 调整边距

_player.defaultEdgeControlLayer.leftMargin = 16;
_player.defaultEdgeControlLayer.rightMargin = 16;

20.8 取消控制层上下视图的阴影

[_player.defaultEdgeControlLayer.topContainerView cleanColors];
[_player.defaultEdgeControlLayer.bottomContainerView cleanColors];

赞助

如果对您有所帮助,欢迎您的赞赏

Comments ( 0 )

Sign in for post a comment

About

No description spread retract
Objective-C
MIT
Cancel

Releases

No release

Contributors

All

Activities

load more
can not load any more