好久没写文章了,最近有点时间,模仿了一个抖音视频上下滑动切换播放功能,顾记录下实现方案,共勉。
一、先说下大致思路:
1.UITableView : Cell上展示视频第一帧图片,点赞,评论,头像等参数
2.封装一个视频播放View
3.定义一个属性currentIndex,并添加他的观察属性,当currentIndex属性值改变时,处理视频播放功能
4.UITableView滑动代理,处理视频上下滑动动画操作
5.注意,整个UITableView中,只存在一个视频播放实例方法,这样性能提升
直播功能的界面展示,也同样处理逻辑
开始之前,info.plist 需要增加麦克风,相册权限
因为是demo,所有代码怎么简单怎么来,谅解!!!
下面是具体代码,供参考,自己直接copy到项目中就可以用,如有需要再讲代码上传都codding
涉及图片资源,自己随便找个图顶下就行
欢迎关注公众号:编程大鑫,进群大家一起交流进步!
![]()
二、代码实现
1,HomeController.h类中
#import "HomeController.h" #import "VideoTableCell.h" //自定义Cell #import "VideoView.h" //位置:松开后切换视频 #define offsetY 100 @interface HomeController ()<UITableViewDataSource,UITableViewDelegate>{ UITableView * table; NSArray * dataArray; //存放视频url NSMutableArray * videoPicArray;//视频第一帧图片,真实情况下后台会返回图片第一帧url } @property(nonatomic,strong)VideoView * videoView;//视频播放器 @property(nonatomic,assign)NSInteger currentIndex;//当前tableview indexPath @end @implementation HomeController - (void)viewDidLoad { [super viewDidLoad]; [self initData]; [self setupView]; //获取视频第一帧 dispatch_async(dispatch_get_global_queue(0,0), ^{ for (int i = 0; i < self->dataArray.count;i++) { UIImage * image = [self getVideoPreViewImage:[NSURL URLWithString:self->dataArray[i]]]; [self->videoPicArray replaceObjectAtIndex:i withObject:image]; dispatch_async(dispatch_get_main_queue(), ^{ [self->table reloadData]; }); } }); } -(void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; //进入界面时,播放 if(self.videoView){ [self.videoView play]; } } -(void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; //离开时暂停播放 if(self.videoView){ [self.videoView pause]; } } -(void)initData{ dataArray=@[ @"https://aweme.snssdk.com/aweme/v1/play/?video_id=ba8f4ff0c1fe445dbfdc1cc9565222fa&line=0&ratio=720p&media_type=4&vr_type=0&test_cdn=None&improve_bitrate=0", @"http://ctgdev.oss-cn-shanghai.aliyuncs.com/zys/04795f79-697b-4647-958b-fed0261b2730.mp4", @"https://aweme.snssdk.com/aweme/v1/play/?video_id=ba8f4ff0c1fe445dbfdc1cc9565222fa&line=0&ratio=720p&media_type=4&vr_type=0&test_cdn=None&improve_bitrate=0", @"http://ctgdev.oss-cn-shanghai.aliyuncs.com/zys/04795f79-697b-4647-958b-fed0261b2730.mp4", @"https://aweme.snssdk.com/aweme/v1/play/?video_id=ba8f4ff0c1fe445dbfdc1cc9565222fa&line=0&ratio=720p&media_type=4&vr_type=0&test_cdn=None&improve_bitrate=0"]; videoPicArray=[NSMutableArray array]; for(int i=0;i<dataArray.count;i++){ [videoPicArray addObject:[UIImage imageNamed:@"img_video_loading"]]; } } -(void)setupView{ navView.backgroundColor=MS_RGBA(0, 0, 0, 0); UILabel * liveLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, StatusHeight+10, 60, 20)]; liveLabel.text=@"直播"; liveLabel.font=[UIFont boldSystemFontOfSize:16]; liveLabel.textAlignment=NSTextAlignmentCenter; liveLabel.textColor=[UIColor whiteColor]; [navView addSubview:liveLabel]; CGFloat leftX = (SCREEN_WIDTH-150)/3; UILabel * locationLabel = [[UILabel alloc] initWithFrame:CGRectMake(leftX+50, StatusHeight+10, 50, 20)]; locationLabel.text=@"本地"; locationLabel.font=[UIFont systemFontOfSize:17]; locationLabel.textAlignment=NSTextAlignmentCenter; locationLabel.textColor=[UIColor whiteColor]; [navView addSubview:locationLabel]; UILabel * likeTitle = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(locationLabel.frame), StatusHeight+10, 50, 20)]; likeTitle.text=@"关注"; likeTitle.font=[UIFont systemFontOfSize:16]; likeTitle.textAlignment=NSTextAlignmentCenter; likeTitle.textColor=[UIColor whiteColor]; [navView addSubview:likeTitle]; UILabel * hotTitle = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(likeTitle.frame), StatusHeight+10, 50, 20)]; hotTitle.text=@"推荐"; hotTitle.font=[UIFont boldSystemFontOfSize:16]; hotTitle.textAlignment=NSTextAlignmentCenter; hotTitle.textColor=[UIColor whiteColor]; [navView addSubview:hotTitle]; UILabel * searchLabel = [[UILabel alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-60, StatusHeight+10, 60, 20)]; searchLabel.text=@"搜索"; searchLabel.font=[UIFont boldSystemFontOfSize:16]; searchLabel.textAlignment=NSTextAlignmentCenter; searchLabel.textColor=[UIColor whiteColor]; [navView addSubview:searchLabel]; table = [[UITableView alloc] initWithFrame:CGRectMake(0,0,SCREEN_WIDTH,SCREEN_HEIGHT)]; table.dataSource = self; table.showsVerticalScrollIndicator = NO; table.delegate=self; table.separatorStyle = UITableViewCellSeparatorStyleNone; table.rowHeight=table.frame.size.height; table.backgroundColor=[UIColor blackColor]; table.scrollsToTop=NO; table.contentInset=UIEdgeInsetsMake(0, 0, TabbarStautsHeight, 0); if (@available(ios 11.0,*)) { [table setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever]; } [self.view addSubview:table]; [self.view addSubview:navView]; [table registerClass:[VideoTableCell class] forCellReuseIdentifier:@"VideoTableCell"]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self addObserver:self forKeyPath:@"currentIndex" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew context:nil];//添加观察者,重点 }); } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return dataArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { VideoTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"VideoTableCell" forIndexPath:indexPath]; //显示视频第一帧图片 cell.bgImageView.image=videoPicArray[indexPath.row]; return cell; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ dispatch_async(dispatch_get_main_queue(), ^{ CGPoint translatedPoint = [scrollView.panGestureRecognizer translationInView:scrollView]; scrollView.panGestureRecognizer.enabled = NO; NSLog(@"UITableView禁止响应其他滑动手势"); if(translatedPoint.y < -offsetY && self.currentIndex < (self->dataArray.count - 1)) { self.currentIndex ++; NSLog(@"向下滑动索引递增"); } if(translatedPoint.y > offsetY && self.currentIndex > 0) { self.currentIndex --; NSLog(@"向上滑动索引递减"); } [UIView animateWithDuration:0.15 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{ [self->table scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.currentIndex inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; } completion:^(BOOL finished) { scrollView.panGestureRecognizer.enabled = YES; NSLog(@"UITableView可以响应其他滑动手势"); }]; }); } //观察currentIndex变化 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"currentIndex"]) { NSLog(@"indexPath发生改变"); /* 整个列表视频播放,只会存在一个播放器 */ VideoTableCell *cell = [table cellForRowAtIndexPath:[NSIndexPath indexPathForRow:self.currentIndex inSection:0]]; [self.videoView removePlayer]; [self.videoView removeFromSuperview]; self.videoView=[[VideoView alloc] initWithFrame:CGRectMake(0, 0,SCREEN_WIDTH, table.rowHeight) url:dataArray[self.currentIndex] image:videoPicArray[self.currentIndex]]; [cell.contentView addSubview:self.videoView]; [cell insertSubview:cell.middleView belowSubview:self.videoView]; WEAKBLOCK(self); self.videoView.changeScreen = ^(BOOL isFull) { STRONGBLOCK(self); cell.bgImageView.hidden=YES; if(isFull){ self.tabBarController.tabBar.hidden = YES; self->navView.hidden=YES; self->table.scrollEnabled=NO; cell.middleView.hidden=YES; }else{ self.tabBarController.tabBar.hidden = NO; self->navView.hidden=NO; self->table.scrollEnabled=YES; cell.middleView.hidden=NO; cell.bgImageView.hidden=NO; } }; } } //mark:一般真实项目,后台会返回视频第一帧图片url给端 // 获取网络视频第一帧 - (UIImage*)getVideoPreViewImage:(NSURL *)path { AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:path options:nil]; AVAssetImageGenerator *assetGen = [[AVAssetImageGenerator alloc] initWithAsset:asset]; assetGen.appliesPreferredTrackTransform = YES; CMTime time = CMTimeMakeWithSeconds(0, 1); NSError *error = nil; CMTime actualTime; CGImageRef image = [assetGen copyCGImageAtTime:time actualTime:&actualTime error:&error]; UIImage *videoImage = [[UIImage alloc] initWithCGImage:image]; CGImageRelease(image); return videoImage; } @end
2,VideoTableCell.h
@property(nonatomic,strong)UIImageView * bgImageView; @property(nonatomic,strong)UIView * middleView;
VideoTableCell.m
#import "VideoTableCell.h" #import "Config.h" @implementation VideoTableCell -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ if(self=[super initWithStyle:style reuseIdentifier:reuseIdentifier]){ self.contentView.backgroundColor=[UIColor blackColor]; CGFloat height = SCREEN_HEIGHT; self.bgImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, height)]; self.bgImageView.tag=100; self.bgImageView.image=[UIImage imageNamed:@"img_video_loading"]; [self.contentView addSubview:self.bgImageView]; self.middleView=[[UIView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH-80, (height-150-StatusHeight)/2, 80, 50)]; self.middleView.tag=200; [self.contentView addSubview:self.middleView]; UILabel * titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 80, 50)]; titleLabel.text=@"头像"; titleLabel.font=[UIFont boldSystemFontOfSize:16]; titleLabel.textColor=[UIColor whiteColor]; titleLabel.textAlignment = 1; [self.middleView addSubview:titleLabel]; UILabel * titleLabel2 = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(titleLabel.frame), 80, 50)]; titleLabel2.text=@"点赞"; titleLabel2.font=[UIFont boldSystemFontOfSize:16]; titleLabel2.textColor=[UIColor whiteColor]; titleLabel2.textAlignment = 1; [self.middleView addSubview:titleLabel2]; UILabel * titleLabel3 = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(titleLabel2.frame), 80, 50)]; titleLabel3.text=@"评论"; titleLabel3.font=[UIFont boldSystemFontOfSize:16]; titleLabel3.textColor=[UIColor whiteColor]; titleLabel3.textAlignment = 1; [self.middleView addSubview:titleLabel3]; } return self; } @end
3,重点来啦,VideoView.h
@interface VideoView : UIView { UIView * sliderView; UIView * bottomView; UILabel *countTimeLabel; UIButton * startVideoBtn; UIButton * changeFullScreenBtn; } ///真实项目中,直接用dict包裹入参 -(instancetype)initWithFrame:(CGRect)frame url:(NSString*)url image:(UIImage*)image; @property (nonatomic,strong)AVPlayer *player;//播放器对象 @property(nonatomic,strong) AVPlayerLayer *avLayer; //展示播放View @property(nonatomic,strong)UILabel * currentTimeLabel;//当前倒计时 @property (nonatomic,strong)UISlider *slider;//滑竿 @property(nonatomic,assign)BOOL isFullScreen; //是否全屏状态 默认NO @property (nonatomic, assign) CGRect smallFrame; //小屏幕frame @property (nonatomic, assign) CGRect bigFrame; //全屏frame ///点击全屏,取消全屏回调 @property(nonatomic,copy)void(^changeScreen)(BOOL isFull); ///开始播放 -(void)play; ///暂停 -(void)pause; ///移除观察者 -(void)removePlayer;
VideoView.m
#import "VideoView.h" #import "Config.h" @implementation VideoView -(instancetype)initWithFrame:(CGRect)frame url:(NSString*)url image:(UIImage *)image{ if(self=[super initWithFrame:frame]){ self.isFullScreen = NO; self.smallFrame = frame; self.bigFrame = CGRectMake(0, 0,SCREEN_WIDTH, SCREEN_HEIGHT); CGFloat height = frame.size.height; CGFloat width = frame.size.width; //占位,视频第一帧图片 UIImageView* bgImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, width, height)]; bgImageView.image=image; bgImageView.userInteractionEnabled=YES; [self addSubview:bgImageView]; //网络视频路径 NSURL *webVideoUrl = [NSURL URLWithString:url]; AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:webVideoUrl]; self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem]; self.avLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; self.avLayer.backgroundColor=[UIColor blackColor].CGColor; self.avLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; self.avLayer.frame = CGRectMake(0, 0, bgImageView.frame.size.width, bgImageView.frame.size.height); [bgImageView.layer addSublayer:self.avLayer]; sliderView =[[UIView alloc] initWithFrame:frame]; sliderView.hidden=YES; [self addSubview:sliderView]; bottomView=[[UIView alloc] initWithFrame:CGRectMake(0, sliderView.frame.size.height-50-TabbarStautsHeight, frame.size.width, 50)]; bottomView.backgroundColor=MS_RGBA(0, 0, 0, 0.5); [sliderView addSubview:bottomView]; startVideoBtn =[UIButton buttonWithType:UIButtonTypeCustom]; startVideoBtn.frame=CGRectMake(0,0, 50, 50); [startVideoBtn setImage:[UIImage imageNamed:@"videoPauseBtn"] forState:normal]; [startVideoBtn addTarget:self action:@selector(actStartVideo:) forControlEvents:UIControlEventTouchUpInside]; [bottomView addSubview:startVideoBtn]; self.currentTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 50, 50)]; self.currentTimeLabel.textColor=[UIColor whiteColor]; self.currentTimeLabel.text=@"00:00"; self.currentTimeLabel.font=[UIFont systemFontOfSize:14]; self.currentTimeLabel.textAlignment=1; [bottomView addSubview:self.currentTimeLabel]; self.slider=[[UISlider alloc] initWithFrame:CGRectMake(100, 0, SCREEN_WIDTH-200, 50)]; self.slider.minimumValue=0; self.slider.minimumTrackTintColor=[UIColor whiteColor]; self.slider.maximumTrackTintColor =[UIColor colorWithRed:1 green:1 blue:1 alpha:0.5]; [self.slider addTarget:self action:@selector(avSliderAction) forControlEvents: UIControlEventTouchUpInside|UIControlEventTouchCancel|UIControlEventTouchUpOutside]; [self.slider setThumbImage:[UIImage imageNamed:@"slider"] forState:normal]; [bottomView addSubview:self.slider]; countTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(self.slider.frame), 0, 50, 50)]; countTimeLabel.textColor=[UIColor whiteColor]; countTimeLabel.text=@"00:00"; countTimeLabel.font=[UIFont systemFontOfSize:14]; countTimeLabel.textAlignment=1; [bottomView addSubview:countTimeLabel]; changeFullScreenBtn =[UIButton buttonWithType:UIButtonTypeCustom]; changeFullScreenBtn.frame=CGRectMake(CGRectGetMaxX(countTimeLabel.frame),0, 50, 50); [changeFullScreenBtn setImage:[UIImage imageNamed:@"exitFullScreen"] forState:normal]; [changeFullScreenBtn addTarget:self action:@selector(actChange:) forControlEvents:UIControlEventTouchUpInside]; [bottomView addSubview:changeFullScreenBtn]; changeFullScreenBtn.selected=NO; WEAKBLOCK(self); [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1, NSEC_PER_SEC) queue:NULL usingBlock:^(CMTime time) { STRONGBLOCK(self); NSInteger currentTime = CMTimeGetSeconds(self.player.currentItem.currentTime); NSInteger countTime = CMTimeGetSeconds(self.player.currentItem.duration); self.currentTimeLabel.text=[self getMMSSFromSS:[NSString stringWithFormat:@"%zi",currentTime]]; self.slider.value=currentTime; if(currentTime>=countTime){ self.slider.value=0; [self.player seekToTime:CMTimeMake(0, 1)]; } }]; [self.player.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; UITapGestureRecognizer *hidenTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(hiddenBottonView:)]; [self addGestureRecognizer:hidenTap]; } return self; } - (void)hiddenBottonView: (UITapGestureRecognizer *)tap { if (sliderView.hidden) { sliderView.hidden = NO; }else { sliderView.hidden = YES; } } - (void)avSliderAction{ CGFloat seconds = self.slider.value; [self startPlayer:seconds]; } -(void)startPlayer:(CGFloat)seconds{ CMTime startTime = CMTimeMakeWithSeconds(seconds, self.player.currentTime.timescale); [self.player seekToTime:startTime]; } -(void)layoutSubviews{ [super layoutSubviews]; self.avLayer.frame=self.bounds; sliderView.frame=self.bounds; CGFloat topY = !self.isFullScreen?TabbarStautsHeight:0; CGFloat leftX = !self.isFullScreen?0:NavigationHeight; CGFloat spaceWidth = !self.isFullScreen?0:TabbarStautsHeight; bottomView.frame=CGRectMake(0, sliderView.frame.size.height-topY-50, sliderView.frame.size.width, 50); startVideoBtn.frame=CGRectMake(leftX, 0, 50, 50); self.currentTimeLabel.frame = CGRectMake(leftX+50, 0, 50, 50); self.slider.frame=CGRectMake(CGRectGetMaxX(self.currentTimeLabel.frame), 0, sliderView.frame.size.width-100-spaceWidth-CGRectGetMaxX(self.currentTimeLabel.frame), 50); countTimeLabel.frame = CGRectMake(sliderView.frame.size.width-100-spaceWidth, 0, 50, 50); changeFullScreenBtn.frame=CGRectMake(sliderView.frame.size.width-50-spaceWidth, 0, 50, 50); } //观察currentIndex变化 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { if ([keyPath isEqualToString:@"status"]){ //获取playerItem的status属性最新的状态 AVPlayerStatus status = [[change objectForKey:@"new"] intValue]; switch (status) { case AVPlayerStatusReadyToPlay:{ NSInteger countTime = CMTimeGetSeconds(self.player.currentItem.duration); self.slider.maximumValue =countTime; countTimeLabel.text=[self getMMSSFromSS:[NSString stringWithFormat:@"%zi",countTime]]; [self.player play]; break; } case AVPlayerStatusFailed:{//视频加载失败,点击重新加载 NSLog(@"视频播放失败"); break; } case AVPlayerStatusUnknown:{ NSLog(@"视频播放失败"); break; } default: break; } } } -(void)play { [self.player play]; } -(void)pause{ [self.player pause]; } -(void)actStartVideo:(UIButton*)btn{ if(!startVideoBtn.selected){ startVideoBtn.selected=YES; [startVideoBtn setImage:[UIImage imageNamed:@"videoPlayBtn"] forState:normal]; [self pause]; }else{ startVideoBtn.selected=NO; [startVideoBtn setImage:[UIImage imageNamed:@"videoPauseBtn"] forState:normal]; [self play]; } } -(void)actChange:(UIButton*)btn{ if(!changeFullScreenBtn.selected){ self.isFullScreen=YES; changeFullScreenBtn.selected=YES; [changeFullScreenBtn setImage:[UIImage imageNamed:@"exitFullScreen"] forState:normal]; [UIView animateWithDuration:0.3 animations:^{ self.transform = CGAffineTransformMakeRotation(M_PI / 2); } completion:nil]; self.frame=self.bigFrame; if(self.changeScreen){ self.changeScreen(self.isFullScreen); } }else{ changeFullScreenBtn.selected=NO; self.isFullScreen=NO; [changeFullScreenBtn setImage:[UIImage imageNamed:@"kr-video-player-fullscreen"] forState:normal]; [UIView animateWithDuration:0.3 animations:^{ self.transform = CGAffineTransformMakeRotation(M_PI * 2); } completion:^(BOOL finished) { if(self.changeScreen){ self.changeScreen(self.isFullScreen); } }]; self.frame=self.smallFrame; } } -(void)removePlayer{ [self.player.currentItem removeObserver:self forKeyPath:@"status"]; [self.player pause]; } -(NSString *)getMMSSFromSS:(NSString *)totalTime{ NSInteger seconds = [totalTime integerValue]; NSString *str_minute = [NSString stringWithFormat:@"%02ld",seconds/60]; NSString *str_second = [NSString stringWithFormat:@"%02ld",seconds%60]; NSString *format_time = [NSString stringWithFormat:@"%@:%@",str_minute,str_second]; return format_time; } @end
4,config.h文件里常用方法
#ifndef Config_h #define Config_h ///判断是否为iPhone X 系列 #define iPhoneX \ ({BOOL isPhoneX = NO;\ if (@available(iOS 11.0, *)) {\ isPhoneX = [[UIApplication sharedApplication] delegate].window.safeAreaInsets.bottom > 0.0;\ }\ (isPhoneX);}) #define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width) #define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height) #define GL_isPad ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) #define GL_isIPhone_Xr ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(828, 1792), [[UIScreen mainScreen] currentMode].size) && !GL_isPad : NO) #define GL_isIPhone_Xs ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) && !GL_isPad : NO) #define GL_isIPhone_Xs_Max ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1242, 2688), [[UIScreen mainScreen] currentMode].size) && !GL_isPad : NO) #define GL_isIPhone_iPhone12_Mini ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1080, 2340), [[UIScreen mainScreen] currentMode].size) && !GL_isPad : NO) #define GL_isIPhone_X ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) && !GL_isPad : NO) #define GL_isIPhone_iPhone12 ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1170, 2532), [[UIScreen mainScreen] currentMode].size) && !GL_isPad : NO) #define GL_isIPhone_iPhone12_ProMax ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1284, 2778), [[UIScreen mainScreen] currentMode].size) && !GL_isPad : NO) ///导航栏高度 #define NavigationHeight ((GL_isIPhone_Xr == YES || GL_isIPhone_Xs == YES || GL_isIPhone_Xs_Max == YES || GL_isIPhone_iPhone12_Mini == YES) ? 88.0 : (GL_isIPhone_X == YES) ? 92 : (GL_isIPhone_iPhone12 == YES || GL_isIPhone_iPhone12_ProMax == YES) ? 91 : 64.0) ///若果是iPhoneX 则底部减去一个半圆弧度高 #define TabbarHeight (iPhoneX?34:0) ///状态栏 #define StatusHeight [[UIApplication sharedApplication] statusBarFrame].size.height #define TabbarStautsHeight (iPhoneX?83:49) #define MS_RGBA(r,g,b,a) [UIColor colorWithRed:(r)/255.0f green:(g)/255.0f blue:(b)/255.0f \ alpha:(a)] ///WEAKBLOCK #define WEAKBLOCK(type) __weak __typeof(type) weak##type = type ///STRONGBLOCK #define STRONGBLOCK(type) __strong __typeof(type) type = weak##type #endif /* Config_h */
至此,仿抖音视频上下滑动切换功能已完成。