神刀安全网

iOS 图解一个功能很全的视频播放器的使用

大家好, 上一次我分享了一个视频播放器(SJVideoPlayer), 今天我再给大家分享一下它的使用图解, 希望大家喜欢. 对了, 本项目除了全屏手势hook了一下nav的push方法, 其它功能都对原始项目无任何侵害. 您可以放心的使用(全屏手势如果不顺心也可以方便的移除).

上一次分享的文章链接: https://www.jianshu.com/p/4c2a493fb4bf

下面请看这款用心写的播放器吧. 就从最简单的开始吧😝

播放资源的初始化及三板斧

  • 播放器在普通视图上播放:

    iOS 图解一个功能很全的视频播放器的使用

    在UIView上播放.png

/// 以下为示例:     _videoPlayer = [SJVideoPlayer player];     _videoPlayer.view.frame = CGRectMake(0, 20, 375, 375 * 9/16.0); // 可以使用AutoLayout, 这里为了简便设置的Frame.     [self.view addSubview:_videoPlayer.view];     // 初始化资源     _videoPlayer.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithAssetURL:[NSURL URLWithString:@"http://..."]];     // 当然也可以指定开始时间. 如下, 从第20秒开始播放     // _videoPlayer.URLAsset = [[SJVideoPlayerURLAsset alloc] initWithAssetURL:[NSURL URLWithString:@"http://..."] beginTime:20.0]; 

  • 播放器在UITableViewCell或UICollectionViewCell中播放:

    iOS 图解一个功能很全的视频播放器的使用

    播放器在UITableViewCell或UICollectionViewCell中播放.png

/// 以下为示例: /// UICollectionView同UITableView初始化一致, 所以此处仅展示UITableView的示例. - (void)clickedPlayBtnOnTabCell:(SJVideoListTableViewCell *)cell playerSuperview:(UIView *)playerSuperview {     //  1. 创建一个播放资源     SJVideoPlayerURLAsset *asset =     [[SJVideoPlayerURLAsset alloc] initWithAssetURL:[NSURL URLWithString:@"https://..."]                                           beginTime:20                                          scrollView:self.tableView                                           indexPath:[self.tableView indexPathForCell:cell]                                        superviewTag:playerSuperview.tag]; // 请务必设置tag, 且不能等于0. 由于重用机制, 当视图滚动时, 播放器需要通过此tag寻找其父视图     // 2. 设置资源标题     asset.title = @"DIY心情转盘 #手工##手工制作##卖包子喽##1块1个##卖完就撤#";     // 3. 默认情况下, 小屏时不显示标题, 全屏后才会显示, 这里设置一直显示标题     asset.alwaysShowTitle = YES;        _videoPlayer = [SJVideoPlayer player];     [playerSuperview addSubview:_videoPlayer.view];     [_videoPlayer.view mas_makeConstraints:^(MASConstraintMaker *make) {         make.edges.offset(0);     }];     // 设置资源     _videoPlayer.URLAsset = asset; } 

  • 播放器在tableHeaderView上播放:

    iOS 图解一个功能很全的视频播放器的使用

    播放器在tableHeaderView上播放.png

/// 以下为示例:         __weak typeof(self) _self = self;     // table header btn clicked event.     self.tableHeaderView.clickedPlayBtnExeBlock = ^(TableHeaderView * _Nonnull playerSuperview) {         __strong typeof(_self) self = _self;         if ( !self ) return;         //  1. 创建一个播放资源         SJVideoPlayerURLAsset *asset =         [[SJVideoPlayerURLAsset alloc] initWithAssetURL:[NSURL URLWithString:@"https://..."]                                               beginTime:0                            playerSuperViewOfTableHeader:playerSuperview                                               tableView:self.tableView];         // 2. 设置资源标题         asset.title = @"DIY心情转盘 #手工##手工制作#";         // 3. 默认情况下, 小屏时不显示标题, 全屏后才会显示, 这里设置一直显示标题         asset.alwaysShowTitle = YES;          self.videoPlayer = [SJVideoPlayer player];         [playerSuperview addSubview:self.videoPlayer.view];         [self.videoPlayer.view mas_makeConstraints:^(MASConstraintMaker *make) {             make.edges.offset(0);         }];         // 设置资源         self.videoPlayer.URLAsset = asset;     }; 

  • 播放器在UICollectionViewCell中播放, 同时UICollectionView在tableHeaderView中:

    iOS 图解一个功能很全的视频播放器的使用

    播放器在UICollectionViewCell中播放, 同时UICollectionView在tableHeaderView中.png

/// 以下为示例:     __weak typeof(self) _self = self;     _tableHeaderView.clickedPlayBtnExeBlock = ^(TableHeaderCollectionView *view, UICollectionView *collectionView, NSIndexPath *indexPath, UIView *playerSuperview) {         __strong typeof(_self) self = _self;         if ( !self ) return;         //  1. 创建一个播放资源         SJVideoPlayerURLAsset *asset =         [[SJVideoPlayerURLAsset alloc] initWithAssetURL:[NSURL URLWithString:@"https://..."]                                               beginTime:0                             collectionViewOfTableHeader:collectionView                                 collectionCellIndexPath:indexPath                                      playerSuperViewTag:playerSuperview.tag                                           rootTableView:self.tableView];                  // 2. 设置资源标题         asset.title = @"DIY心情转盘 #手工##手工制作#";         // 3. 默认情况下, 小屏时不显示标题, 全屏后才会显示, 这里设置一直显示标题         asset.alwaysShowTitle = YES;          self.videoPlayer = [SJVideoPlayer player];         [playerSuperview addSubview:self.videoPlayer.view];         [self.videoPlayer.view mas_makeConstraints:^(MASConstraintMaker *make) {             make.edges.offset(0);         }];         // 设置资源         self.videoPlayer.URLAsset = asset;     }; 

  • 播放器在UICollectionCell中播放, 同时UICollectionView在UITableViewCell中:

    iOS 图解一个功能很全的视频播放器的使用

    播放器在UICollectionCell中播放, 同时UICollectionView在UITableViewCell中.png

/// 以下为示例: - (void)clickedPlayWithTableViewCell:(NestedTableViewCell *)tabCell                      playerSuperview:(UIView *)playerSuperview          collectionViewCellIndexPath:(NSIndexPath *)collectionViewCellIndexPath                       collectionView:(UICollectionView *)collectionView {     //  1. 创建一个播放资源     NSIndexPath *collectionViewIndexPath = [self.tableView indexPathForCell:tabCell];     SJVideoPlayerURLAsset *asset =     [[SJVideoPlayerURLAsset alloc] initWithAssetURL:playURL                                           beginTime:0                                           indexPath:collectionViewCellIndexPath                                        superviewTag:playerSuperview.tag                                 scrollViewIndexPath:collectionViewIndexPath                                       scrollViewTag:collectionView.tag                                      rootScrollView:self.tableView];     // 2. 设置资源标题     asset.title = @"DIY心情转盘 #手工##手工制作#";     // 3. 默认情况下, 小屏时不显示标题, 全屏后才会显示, 这里设置一直显示标题     asset.alwaysShowTitle = YES;      self.videoPlayer = [SJVideoPlayer player];     [playerSuperview addSubview:self.videoPlayer.view];     [self.videoPlayer.view mas_makeConstraints:^(MASConstraintMaker *make) {             make.edges.offset(0);     }];     // 设置资源     self.videoPlayer.URLAsset = asset; } 

资源三板斧

  • 资源刷新. 在播放一个资源时, 可能有一些意外情况导致播放失败(如网络环境差). 此时当用户点击刷新按钮, 我们需要对当前的资源(Asset)进行刷新. SJVideoPlayer提供了直接的方法去刷新, 不需要开发者再重复的去创建新的Asset.
/// 以下为示例:     // 对当前资源进行刷新, 尝试重新播放视频     [_videoPlayer refresh]; 
  • 记录某个播放位置. 我们有时候想存储某个视频的播放记录, 以便下次, 能够从指定的位置进行播放. 那什么时候存储合适呢? 最好的时机就是资源被释放时. SJVideoPlayer提供了每个资源在Dealloc中, 都进行的回调, 如下:
/// 以下为示例:      // 每个资源dealloc时的回调     _videoPlayer.assetDeallocExeBlock = ^(__kindof SJBaseVideoPlayer * _Nonnull videoPlayer) {       // .....     }; 
  • 续播. 在播放时, 我们可能需要切换界面, 而希望视频能够在下一个界面无缝的进行播放. 针对此种情况 SJVideoPlayerURLAsset 提供了便利的初始化方法. 请看片段:
+ (instancetype)assetWithOtherAsset:(SJVideoPlayerURLAsset *)asset; + (instancetype)assetWithOtherAsset:(SJVideoPlayerURLAsset *)asset                          scrollView:(__unsafe_unretained UIScrollView * __nullable)tableOrCollectionView                           indexPath:(NSIndexPath * __nullable)indexPath                        superviewTag:(NSInteger)superviewTag; + (instancetype)assetWithOtherAsset:(SJVideoPlayerURLAsset *)asset        playerSuperViewOfTableHeader:(__unsafe_unretained UIView *)superView                           tableView:(__unsafe_unretained UITableView *)tableView; + (instancetype)assetWithOtherAsset:(SJVideoPlayerURLAsset *)asset         collectionViewOfTableHeader:(__unsafe_unretained UICollectionView *)collectionView             collectionCellIndexPath:(NSIndexPath *)indexPath                  playerSuperViewTag:(NSInteger)playerSuperViewTag                       rootTableView:(__unsafe_unretained UITableView *)rootTableView; + (instancetype)assetWithOtherAsset:(SJVideoPlayerURLAsset *)asset                           indexPath:(NSIndexPath *__nullable)indexPath                        superviewTag:(NSInteger)superviewTag                 scrollViewIndexPath:(NSIndexPath *__nullable)scrollViewIndexPath                       scrollViewTag:(NSInteger)scrollViewTag                      rootScrollView:(__unsafe_unretained UIScrollView *__nullable)rootScrollView;  /// 以下为示例:   // 新界面的播放器, 资源初始化:     _videoPlayer = [SJVideoPlayer player];     _videoPlayer.view.frame = CGRectMake(0, 20, 375, 375 * 9/16.0); // 可以使用AutoLayout, 这里为了简便设置的Frame.     [self.view addSubview:_videoPlayer.view];     // 初始化资源     _videoPlayer.URLAsset = [SJVideoPlayerURLAsset assetWithOtherAsset:otherAsset];  

是的, otherAsset即为上一个页面播放的Asset, 只要用它进行初始化即可实现续播功能. 同时可以发现, 初始化时, 除了需要一个otherAsset, 其他方面同开始的示例一模一样.

请看下图:

iOS 图解一个功能很全的视频播放器的使用

image


优雅自如的旋转

对于旋转, 我们开发者肯定需要绝对的控制, 例如: 设置自动旋转所支持方向. 能够主动+自动旋转, 而且还需要能在适当的时候禁止自动旋转. 旋转前后的回调等等… 放心这些功能都有, 我挨个给大家介绍一下:

先说说何为自动旋转. 其实就是播放器根据当前设备的方向, 进行自动旋转.

  • 设置自动旋转所支持方向, SJVideoPlayer自动旋转支持的方向如下:
/// 自动旋转所支持的方向 typedef NS_ENUM(NSUInteger, SJAutoRotateSupportedOrientation) {     SJAutoRotateSupportedOrientation_All,     SJAutoRotateSupportedOrientation_Portrait = 1 << 0,     SJAutoRotateSupportedOrientation_LandscapeLeft = 1 << 1,  // UIDeviceOrientationLandscapeLeft     SJAutoRotateSupportedOrientation_LandscapeRight = 1 << 2, // UIDeviceOrientationLandscapeRight }; 

以上为自动旋转时, 所支持的方向, 播放器默认为SJAutoRotateSupportedOrientation_All. 当我们不想让播放器旋转到某个方向时, 可以如下设置:

/// 以下为示例:     // 例如设置播放器只能在全屏方向上旋转     _videoPlayer.supportedOrientation = SJAutoRotateSupportedOrientation_LandscapeLeft | SJAutoRotateSupportedOrientation_LandscapeRight; 

  • 主动旋转. 当我们想主动旋转时, 大概分为以下三点:
    • 主动旋转. 播放器旋转到用户当前的设备方向或小屏.
    • 主动旋转到指定方向.
    • 主动旋转完成后的回调.

请看以下方法, 分别对应以上三点:

 - (void)rotate; - (void)rotate:(SJOrientation)orientation animated:(BOOL)animated; - (void)rotate:(SJOrientation)orientation animated:(BOOL)animated completion:(void (^ _Nullable)(__kindof SJBaseVideoPlayer *player))block;  // 调用示例: [_videoPlayer rotate]; // 主动旋转, 让播放器旋转到用户当前的设备方向或小屏. 

  • 旋转前后的回调. 我们在播放一个视频时, 小屏播的时候, 状态栏的style一般为UIStatusBarStyleDefault. 但是全屏播放视频时, 状态栏就得变成UIStatusBarStyleLightContent, 看下图对比:
    • iOS 图解一个功能很全的视频播放器的使用

      白条.png

    • iOS 图解一个功能很全的视频播放器的使用

      黑条.png

      额, 我们赶紧说回调吧, 状态栏还是变成白的好一点. 旋转前的回调以及旋转后的回调如下:

/// 旋转前的回调 @property (nonatomic, copy, nullable) void(^willRotateScreen)(__kindof SJBaseVideoPlayer *player, BOOL isFullScreen); /// 旋转后的回调 @property (nonatomic, copy, nullable) void(^rotatedScreen)(__kindof SJBaseVideoPlayer *player, BOOL isFullScreen);  /// 以下为示例:  // 旋转前的示例(我常用旋转前的block, 旋转后的block基本没用过😝): // 1. 设置播放器旋转前的回调.      _videoPlayer.willRotateScreen = ^(SJVideoPlayer * _Nonnull player, BOOL isFullScreen) {         __strong typeof(_self) self = _self;         if ( !self ) return ;         [UIView animateWithDuration:0.25 animations:^{             [self setNeedsStatusBarAppearanceUpdate];         }];     }; // 2. 根据控制层的显示状态 去控制状态栏的显示和隐藏 - (BOOL)prefersStatusBarHidden {   // 全屏播放时, 使状态栏根据控制层显示或隐藏   if ( self.videoPlayer.isFullScreen ) return !self.videoPlayer.controlLayerAppeared;   return NO; } // 3. 如果播放器为全屏显示时, 返回状态栏的style为UIStatusBarStyleLightContent, 小屏返回 UIStatusBarStyleDefault - (UIStatusBarStyle)preferredStatusBarStyle {   // 全屏播放时, 使状态栏变成白色   if ( self.videoPlayer.isFullScreen ) return UIStatusBarStyleLightContent;   return UIStatusBarStyleDefault; } 

  • 禁止自动旋转. 这个功能是必须有的, 如果不禁止旋转, 请看图:

    iOS 图解一个功能很全的视频播放器的使用

    需要禁止旋转.gif

    SJVideoPlayer可以通过如下方式禁止自动旋转:

// 禁止自动旋转.  _videoPlayer.disableAutoRotation = YES; 

这里有两点需要注意: 1. 返回时要记得恢复自动旋转. 2. 禁止自动旋转后, 手动点击全屏按钮, 还是可以旋转的.


  • 禁止任何旋转. 也就是锁屏. 请看图:

    iOS 图解一个功能很全的视频播放器的使用

    锁屏.gif

请注意: 在锁屏状态下, 此时不管是主动旋转, 还是自动旋转, 都将不触发. 代码如下:

/// 锁屏 _videoPlayer.lockedScreen = YES; 

  • 还有一些其他便利的属性, 如下:
/// 是否是全屏 @property (nonatomic, readonly) BOOL isFullScreen; /// 当前播放器的方向 @property (nonatomic) SJOrientation orientation; /// 当前播放器旋转到的设备方向 @property (nonatomic, readonly) UIInterfaceOrientation currentOrientation; 

播放的控制

SJVideoPlayer的常规播放控制大概有: 静音, 自动播放, 使播放, 使暂停, 使停止, 使重播.
哦, 对了还有亮度, 声音, 速率(rate)这些的设置. 并且都有相应的回调. 代码我就不贴了, 一看就明白了.

我再介绍一下其他的控制功能:

/**  关于后台播放视频, 引用自: 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`  */ @property (nonatomic) BOOL pauseWhenAppDidEnterBackground;  // 示例: _videoPlayer.pauseWhenAppDidEnterBackground = YES; // 请记得按上述注释的步骤配置 

  • 播放完毕的回调. 我们有时候希望能够重复的播放一个视频. 这时可能需要监听当前的视频有没有播放结束. SJVideoPlayer 提供了播放视频完毕后的回调, 代码如下:
    __weak typeof(self) _self = self;     _videoPlayer.playDidToEnd = ^(__kindof SJBaseVideoPlayer * _Nonnull player) {         __strong typeof(_self) self = _self;         if ( !self ) return ;         [player replay];     } 

如上, 当播放完毕时, 播放器调用 replay 方法, 让其从头重新开始播放.


网络状态变更时的提示

有时候我们需要能够友好的告诉客户当前的网络状态发生了改变, 毕竟流量是要钱的. 我们继续看图:

iOS 图解一个功能很全的视频播放器的使用

网络状态变更提示.png

这些提示, 我都做了本地化处理, 支持的语言有: 中文/繁体/英文. 开发者也可以自己定义想要的提示. 后面我会介绍SJVideoPlayer全局的配置类, 它可以配置各个控件的图片, slider, 本地化的一些提示等等.


夜已深, 请看下回

由于内容比较多, 就介绍到这里吧(熬夜到1点了… 明天还要上班😔), 下一篇我会介绍全局的配置类, 还有如何无缝的替换掉原始控制层, 同时保留自己想要的控制层(切换器).

对了最后唠叨一下, 恳请尊重开源作者的劳动成果, 引用或参照还请注明来源. 谢谢.

另外这是我的联系方式, 希望与您交流:

项目地址: https://github.com/changsanjiang/SJVideoPlayer

我的邮箱: changsanjiang@gmail.com

如果您有什么建议, 望请联系我!

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » iOS 图解一个功能很全的视频播放器的使用

分享到:更多 ()