最近应项目需求,实如今 tableView中添加视频自动播放功能,产品功能相似与微博的视频信息流播放样式,为此实现了好一段时间,如今把当初实现的方法以及内容记录于此,以便后续回顾以及查看。git
视频屏幕居中播放github
由于以前没有作过这样的功能,因此也是作了很多调研工做,由于微博的视频很具备表明性,因此以此为研究对象,构思了一下相关的播放逻辑内容。算法
注意到微博视频播放是居中位置播放,也就是说距离中心位置最近的视频播放 cell 进行自动播放,而其余 cell 中的视频处于中止状态,显然这是一个屏幕居中选定视频的一个算法,而这个算法也这是控制视频播放的核心内容。为此实现它也有了相应的思路,而这块内容大体能够分为三个步骤:数组
使用单例进行视频的有序播放bash
仔细看了一下微博的视频播放,会发现信息流中的视频始终都是一个视频在播放,不管怎么滑动,都是一个视频在当前播放,我想这么作无疑也是两点,一是保证视频播放的惟一性,二则是减小内存的占用。若是每一个 cell 中都添加一个视频播放器的话,也会占用很多内存吧。还有一点就是,若是设计成单例进行视频播放的话,整个信息流中视频播放体系就会变得很好控制,逻辑也会变得愈发清晰。因此这种状况下的视频播放设计成单例播放无疑是最好的选择。网络
控制滚动判断视频播放的时机ide
由于要不断的找出在屏幕中显示的 cell,以及要比较出当前离屏幕中最近的视频cell,因此这个过程若是放在 tableView 中的 didScrollview 方法中判断的话,会在滑动的时候疯狂比较查找,这样作显然是很差的。因此滚动过程当中咱们尽可能不去判断这些逻辑,在滚动中止的时候再去触发判断的逻辑,这样既可以知足自动播放的功能,也省去了来回比较的逻辑过程。因此咱们能够在 tableview 的scrollViewDidEndDragging
与scrollViewDidEndDecelerating
回调中进行判断。ui
有了思路,接下来就是实现了,其实实现方式多种多样,重在思想。spa
视频屏幕居中播放设计
该功能的实现实际上主要在于找到当前屏幕中距离屏幕中线距离最近的 cell,而后选中 cell,让其进行播放也就达到了播放的目的,代码以下:
/* 进行视频自动播放断定逻辑判断 */
- (void)handleScrollPlay{
LCVideoCell *cell = (LCVideoCell *)[self getMinCenterCell];
if (cell && ![self.playingCell isEqual:cell]) {
NSLog(@"当前的 cell 存在,是%ld",cell.tag);
cell.backgroundColor = [UIColor redColor];
if (self.playingCell) {
LCVideoCell *playingCell = (LCVideoCell *)self.playingCell;
playingCell.backgroundColor = [UIColor whiteColor];
}
self.playingCell = cell;
}
}
/* 获取距离屏幕最中间的cell */
- (id)getMinCenterCell{
CGFloat minDelta = CGFLOAT_MAX;
//屏幕中央位置
CGFloat screenCenterY = SCREEN_HEIGHT * 0.5;
//当前距离屏幕中央最近的cell
id minCell = nil;
for (id cell in self.visibleCells) {
if ([cell isKindOfClass:[LCVideoCell class]]) {
LCVideoCell *videoCell = (LCVideoCell *)cell;
//获取当前 cell 的居中点坐标
CGPoint cellCenterPoint = CGPointMake(videoCell.frame.origin.x, videoCell.frame.size.height * 0.5 + videoCell.frame.origin.y);
//转换当前的 cell 的坐标
CGPoint coorPoint = [videoCell.superview convertPoint:cellCenterPoint toView:nil];
CGFloat deltaTemp = fabs(coorPoint.y - screenCenterY);
if (deltaTemp < minDelta) {
minCell = videoCell;
minDelta = deltaTemp;
}
}
}
return minCell;
}
复制代码
判断当前的播放的 cell 是否已经移动到屏幕外面
这个判断逻辑主要是实如今移出到屏幕外以后,视频应该中止的功能,因此为此咱们须要写一个方法去判断当前播放的 cell 的可见性。以及在滚动图中实时判断当前的播放的cell是否已经移动到屏幕外面。判断的代码以下:
/* 当前播放的视频是否划出屏幕 */
- (BOOL)playingCellIsOutScreen{
if (!self.playingCell) {
return YES;
}
LCVideoCell *videoCell = (LCVideoCell *)self.playingCell;
//当前显示区域内容
CGRect visiableContentZone = [UIScreen mainScreen].bounds;
//向上滚动
if(self.scrollDirection == LC_SCROLL_UP){
//找到滚动时候的正在播放视频的cell底部的y坐标点,计算出当前播放的视频是否移除到屏幕外
CGRect playingCellFrame = videoCell.frame;
//当前正在播放视频的坐标
CGPoint cellBottomPoint = CGPointMake(playingCellFrame.origin.x, playingCellFrame.size.height + playingCellFrame.origin.y);
//坐标系转换(转换到 window坐标)
CGPoint coorPoint = [videoCell.superview convertPoint:cellBottomPoint toView:nil];
return CGRectContainsPoint(visiableContentZone, coorPoint);
}
//向下滚动
else if(self.scrollDirection == LC_SCROLL_DOWN){
//找到滚动时候的正在播放视频的cell底部的y坐标点,计算出当前播放的视频是否移除到屏幕外
CGRect playingCellFrame = videoCell.frame;
//当前正在播放视频的坐标
CGPoint orginPoint = CGPointMake(playingCellFrame.origin.x, playingCellFrame.origin.y);
//坐标系转换(转换到 window坐标)
CGPoint coorPoint = [videoCell.superview convertPoint:orginPoint toView:nil];
return CGRectContainsPoint(visiableContentZone, coorPoint);
}
else{
return NO;
}
return YES;
}
复制代码
视频自动选择播放的效果以下所示
视频的居中播放思想就是这样,固然播放器以及网络的判断应该是播放器播放内部的处理方案了,但愿可以给正在开发或者想要开发视频自动选择播放的同窗们一点小小的启发。