项目需求:产品详情页的轮播图做成视频与图片的混合轮播,类似于淘宝的界面,第一个图为产品的视频介绍,其余为图片介绍,本篇 demo
demo预览图
思路:
1、轮播图我们可以用UICollectionView或者是UIScrollView来实现,本篇demo使用的是后者。
2、根据数据的类型判断第一张图是否是视频类型。
3、若第一张是视频类型,则将自定义视频的view加入到UIScrollView中。
4、自定义视频的view可以使用系统的AVPlayerViewController,也可以自定义AVPlayer来实现视频的播放。
5、给自定义的视频view加上遮罩,遮罩的作用是控制视频的暂停与播放,显示进度条的进度等等。
一、UIScrollView 轮播图的创建
1、新建一个view,创建一个类方法,进行初始化,传入要显示的数据
+ (instancetype)scrollViewFrame:(CGRect)frame imageStringGroup:(NSArray *)imgArray {
XQCarousel *carousel = [[self alloc] initWithFrame:frame];
carousel.contentArray = imgArray;
return carousel;
}
2、初始化控件,并加载数据,实现UIScrollView的协议,当滑动的时候 控制视频的暂停与播放
- (void)loadUI {
self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
self.scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
self.scrollView.contentSize = CGSizeMake(self.frame.size.width * self.contentArray.count, self.frame.size.height);
self.scrollView.pagingEnabled = YES;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.delegate = self;
[self addSubview:self.scrollView];
for (NSInteger index = 0; index < self.contentArray.count; index ++) {
UIImageView *img = [[UIImageView alloc]initWithFrame:CGRectMake(self.frame.size.width * index, 0, self.frame.size.width, self.frame.size.height)];
img.image = [UIImage imageNamed:self.contentArray[index]];
/** 测试 **/
if (index == 0) {
self.videoView = [XQVideoView videoViewFrame:img.frame videoUrl:self.contentArray[index]];
self.videoView.videoUrl = self.contentArray[index];
[self.scrollView addSubview:self.videoView];
}else {
[self.scrollView addSubview:img];
}
}
self.pageControl = [[UIPageControl alloc]init];
self.pageControl.frame = CGRectMake(0, self.frame.size.height - 30, self.frame.size.width, 30);
self.pageControl.numberOfPages = self.contentArray.count;
self.pageControl.currentPage = 0;
self.pageControl.currentPageIndicatorTintColor = [UIColor redColor];
[self addSubview:self.pageControl];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSInteger currentPage = round(scrollView.contentOffset.x / self.frame.size.width);
self.pageControl.currentPage = currentPage;
if (self.videoView.isPlay) {
if (currentPage == 0) {
[self.videoView start];
}else {
[self.videoView stop];
}
}
}
二、新建VideoView,初始化AVPlayerViewController,具体实现见demo,主要用到AVPlayerViewController中AVPlayer的两个方法。
// ****** 获取视频的播放进度 控制进度条的显示 ******
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;
// ****** 控制播放器的播放进度,本篇demo用来控制重新播放 ******
- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL finished))completionHandler NS_AVAILABLE(10_7, 5_0);
三、给VideoView加一个遮罩,在其view上添加开始与重新播放的按钮、进度条和单击手势。
#import "VideoMaskView.h"
@interface VideoMaskView ()
// ******* 底部进度条 *******
@property (nonatomic, strong) UIProgressView *progressView;
// ******* 开始播放按钮 *******
@property (nonatomic, strong) UIButton *stratButton;
// ******* 单击手势 *******
@property (nonatomic, strong) UITapGestureRecognizer *singleTap;
// ******* 重新播放按钮 *******
@property (nonatomic, strong) UIButton *replayButton;
@end
@implementation VideoMaskView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self loadUI];
}
return self;
}
- (void)loadUI {
[self addSubview:self.stratButton];
[self addSubview:self.replayButton];
[self addSubview:self.progressView];
[self createGesture];
}
/*
* 创建手势
*/
- (void)createGesture {
// 单击
self.singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(singleTapAction:)];
self.singleTap.numberOfTouchesRequired = 1; //手指数
self.singleTap.numberOfTapsRequired = 1;
[self addGestureRecognizer:self.singleTap];
}
- (void)singleTapAction:(UITapGestureRecognizer *)tap {
if (self.buttonValue) {
self.buttonValue(XQPlayerStateStart);
}
}
- (void)setIsStartButton:(BOOL)isStartButton {
_isStartButton = isStartButton;
isStartButton ? [self.stratButton setHidden:YES] : [self.stratButton setHidden:NO];
}
- (void)setProgressValue:(CGFloat)progressValue {
_progressValue = progressValue;
self.progressView.progress = progressValue;
progressValue == 1 ? [self.replayButton setHidden:NO] : [self.replayButton setHidden:YES];
}
- (void)playerCurrentTime:(NSInteger)currentTime totalTime:(NSInteger)totalTime sliderValue:(CGFloat)sliderValue {
self.progressValue = sliderValue;
}
- (UIProgressView *)progressView {
if (!_progressView) {
_progressView = [[UIProgressView alloc]initWithFrame:CGRectMake(0, self.frame.size.height - 2, self.frame.size.width, 5)];
_progressView.progressViewStyle = UIProgressViewStyleDefault;
_progressView.progressTintColor = [UIColor orangeColor];
_progressView.progress = 0;
}
return _progressView;
}
- (UIButton *)stratButton {
if (!_stratButton) {
_stratButton = [UIButton buttonWithType:UIButtonTypeCustom];
_stratButton.bounds = CGRectMake(0, 0, 40, 40);
_stratButton.center = self.center;
[_stratButton setImage:[UIImage imageNamed:@"play"] forState:UIControlStateNormal];
[_stratButton addTarget:self action:@selector(startButtonTaped) forControlEvents:UIControlEventTouchUpInside];
}
return _stratButton;
}
- (UIButton *)replayButton {
if (!_replayButton) {
_replayButton = [UIButton buttonWithType:UIButtonTypeCustom];
_replayButton.bounds = CGRectMake(0, 0, 50, 70);
_replayButton.center = self.center;
[_replayButton setImage:[UIImage imageNamed:@"ZFPlayer_repeat_video"] forState:UIControlStateNormal];
_replayButton.hidden = YES;
[_replayButton addTarget:self action:@selector(replayButtonTaped) forControlEvents:UIControlEventTouchUpInside];
}
return _replayButton;
}
- (void)startButtonTaped {
if (self.buttonValue) {
self.buttonValue(XQPlayerStateStart);
}
}
- (void)replayButtonTaped {
if (self.buttonValue) {
self.buttonValue(XQPlayerStateReplay);
}
}
@end
1、本篇demo只是粗略实现了图片和视频轮播,可在实际的项目中根据需要进行修改,本人只是提供了一个思路。
2、推荐 视频播放的第三方 ZFPlayer 。