Brothers, recently a little time, imitate a douyin video slide switch playback function, gu record the implementation scheme, encourage.

1.UITableView: Display the first frame of the video on the Cell, like, comment, profile picture and other parameters 2. 3. Define a property currentIndex, and add its observation property, when currentIndex property value changes, handle the video playback function 4. Note that in the entire UITableView, there is only one video playback instance method, so the performance of the live interface display, also handles the same logic

Before starting, info.plist needs to add microphone, photo album permissions

Because it is demo, all code how simple how to come, understanding!!

The following is the specific code for your reference. You can directly copy it into the project and use it. If necessary, I will talk about codding of code upload

When it comes to picture resources, you can find a picture at the top of the line

2, code implementation 1, homecontroller.h class

#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

Copy the code

2, VideoTableCell. H

@property(nonatomic,strong)UIImageView * bgImageView;
@property(nonatomic,strong)UIView * middleView;

Copy the code

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 = @ "face"; 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 = @ "thumb up"; 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 = @ "comments"; titleLabel3.font=[UIFont boldSystemFontOfSize:16]; titleLabel3.textColor=[UIColor whiteColor]; titleLabel3.textAlignment = 1; [self.middleView addSubview:titleLabel3]; } return self; } @endCopy the code

3. Here comes the big point: VideoView.h

@interface VideoView : UIView { UIView * sliderView; UIView * bottomView; UILabel *countTimeLabel; UIButton * startVideoBtn; UIButton * changeFullScreenBtn; } -(instancetype)initWithFrame:(CGRect)frame url:(NSString*)url image:(UIImage*)image; @property (nonatomic,strong)AVPlayer *player; // Player object @property(nonatomic,strong) AVPlayerLayer *avLayer; view@property (nonatomic,strong)UILabel * currentTimeLabel; @property (nonatomic,strong)UISlider *slider; // spindle@property (nonatomic,assign)BOOL isFullScreen; NO @property (nonatomic, assign) CGRect smallFrame; @property (nonatomic, assign) CGRect bigFrame; @property(nonatomic,copy)void(^changeScreen)(BOOL isFull); /// start play -(void)play; / / / pause - (void) pause; // Remove observer -(void)removePlayer;Copy the code

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

Copy the code

4, common methods in config.h file

#ifndef Config_h #define iPhoneX \ ({BOOL isPhoneX = NO; \ if (@ the 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 navigation bar height 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) #define TabbarHeight (iPhoneX? #define StatusHeight [[UIApplication sharedApplication] statusBarFrame].size TabbarStautsHeight (iPhoneX? 85: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 */Copy the code

Welcome to pay attention to the public number: programming daxin, into the group mutual exchange and progress!

At this point, imitation douyin video sliding up and down switching function has been completed.