iOS开发高仿抖音,上下切换横竖屏播放!

Posted iOS大鑫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS开发高仿抖音,上下切换横竖屏播放!相关的知识,希望对你有一定的参考价值。

好久没写文章了,最近有点时间,模仿了一个抖音视频上下滑动切换播放功能,顾记录下实现方案,共勉。

一、先说下大致思路:
1.UITableView : Cell上展示视频第一帧图片,点赞,评论,头像等参数
2.封装一个视频播放View
3.定义一个属性currentIndex,并添加他的观察属性,当currentIndex属性值改变时,处理视频播放功能
4.UITableView滑动代理,处理视频上下滑动动画操作
5.注意,整个UITableView中,只存在一个视频播放实例方法,这样性能提升
直播功能的界面展示,也同样处理逻辑

开始之前,info.plist 需要增加麦克风,相册权限

因为是demo,所有代码怎么简单怎么来,谅解!!!

下面是具体代码,供参考,自己直接copy到项目中就可以用,如有需要再讲代码上传都codding

涉及图片资源,自己随便找个图顶下就行

欢迎关注公众号:编程大鑫,进群大家一起交流进步!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bi9YqM5B-1627022506398)(//upload-images.jianshu.io/upload_images/2151291-109c6326a56f2eaa.png?imageMogr2/auto-orient/strip|imageView2/2/w/722/format/webp)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DH4vadJr-1627022506399)(//upload-images.jianshu.io/upload_images/2151291-699b477a4032ba83.png?imageMogr2/auto-orient/strip|imageView2/2/w/722/format/webp)]

二、代码实现
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 */

至此,仿抖音视频上下滑动切换功能已完成。

以上是关于iOS开发高仿抖音,上下切换横竖屏播放!的主要内容,如果未能解决你的问题,请参考以下文章

基于Uni-APP多端「h5+小程序+App」高仿抖音小视频|直播|聊天实例

flutter开发仿抖音首页面上下滑动切换播放视频效果

仿抖音上下滑动播放视频(兼容安卓,ios,小程序,h5)

H5+Jquery 仿抖音视屏切换

仿抖音上下滑动播放视频(兼容安卓,ios,小程序,h5)

开源项目高仿抖音项目 就问你服不?