美文网首页
iOS gif banner相关问题

iOS gif banner相关问题

作者: 温柔vs先生 | 来源:发表于2023-01-10 17:35 被阅读0次

这样一个需求,banner上显示gif,并且要求每个GIF必须播放完成后,才可以滑动,这里banner找的是一个第三方ZYBannerView实现的

具体代码实现

//
//  GYGalleryHeadView.m
//  GuiYuSiri
//
//  Created by ftt on 2022/11/15.
//

#import "GYGalleryHeadView.h"
#import "GYBannerModel.h"
#import "GYChoosePhotoView.h"
#import "SDCycleScrollView.h"
#import "EllipsePageControl.h"
#import "GYAIDrawViewController.h"
#import "ZYBannerView.h"
#import "FLAnimatedImageView.h"

@interface GYGalleryHeadView ()<ZYBannerViewDelegate,ZYBannerViewDataSource>
@property (nonatomic, strong) EllipsePageControl *pageControl;

@property (nonatomic, strong) ZYBannerView *bannerView;

@property (nonatomic, strong) NSArray * bannerArray;

@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) NSInteger index;

@end
@implementation GYGalleryHeadView
- (void)dealloc {
    if([self.timer isValid])
    {
        [self.timer invalidate];
        self.timer=nil;
    }
}
-(instancetype)initWithFrame:(CGRect)frame{
    self=[super initWithFrame:frame];
    if(self){
        
        [self initbanner];
        
        self.gallerTitleL=[[UILabel alloc] initWithFrame:CGRectMake(14*ScaleWidth, self.frame.size.height-26*ScaleWidth, 56*ScaleWidth, 14*ScaleWidth)];
        [self addSubview:self.gallerTitleL];
        self.gallerTitleL.text=@"作品展览";
        self.gallerTitleL.font=FontSemiboldSize(14);
      
        
        UIImage *refreImg=[UIImage imageNamed:@"ai_draw_search_light"];
        
        self.refreshBtn=[[GYButton alloc] initWithFrame:CGRectMake(ViewWidth-refreImg.size.width-12*ScaleWidth, self.frame.size.height-refreImg.size.height-12*ScaleWidth, refreImg.size.width, refreImg.size.height)];
        [self addSubview:self.refreshBtn];
      
        
      MJWeakSelf
        self.tkThemeChangeBlock = ^(id  _Nullable itself, NSUInteger themeIndex) {
            if (themeIndex == 1) {//白底
                [weakSelf.refreshBtn setImage:[UIImage imageNamed:@"ai_draw_search_dark"] forState:0];
                weakSelf.gallerTitleL.textColor=[UIColor colorWithHexString:@"#000000"];
            } else {//黑底
                [weakSelf.refreshBtn setImage:[UIImage imageNamed:@"ai_draw_search_light"] forState:0];
                weakSelf.gallerTitleL.textColor=[UIColor whiteColor];
            }
        };
        
        
        
        [self requestBanner];
    }
    return self;
    
}




- (void)requestBanner {
    NSString *url = [NSString stringWithFormat:@"%@guiyu-prompter-manager/baseConfig/get?namespace=ai-drawing",LiveBaseUrl];
    [[HttpClient manager] requestWithBaseURL:url para:nil headers:nil httpMethod:HttpMethodGet success:^(id responseObject) {
        if ([GYCODE isEqualToString:@"0"]) {
            NSDictionary *data = responseObject[@"data"];
            NSDictionary *spaceDict = data[@"banner"];
            NSArray * exValueJson = [NSArray arrayWithArray:spaceDict[@"extValueJson"]];

            self.bannerArray = [GYBannerModel mj_objectArrayWithKeyValuesArray:exValueJson];

//            if (self.bannerArray.count <= 1) {
//                [self.bannerView setAutoScroll:NO];
//            } else {
//                [self.bannerView setAutoScroll:YES];
//            }

            self.pageControl.numberOfPages = self.bannerArray.count;
            if (self.bannerArray.count >= 2) {
                self.pageControl.hidden = NO;
            } else {
                self.pageControl.hidden = YES;
            }
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.bannerView reloadData];
                self.index = 0;

            });
            
            
        } else {

        }
    } failure:^(NSURLSessionDataTask *task, NSError *error) {
//        block(NO,@"",nil);
    }];
}
- (void)afterTime:(CGFloat)time {

    if([self.timer isValid])
    {
        [self.timer invalidate];
        self.timer=nil;
    }
   
    self.timer=[NSTimer scheduledTimerWithTimeInterval:time target:self selector:@selector(delayMethod) userInfo:nil repeats:NO];
//    [self performSelector:@selector(delayMethod) withObject:nil afterDelay:time];

}
- (void)delayMethod {
    self.index ++;
    if(self.index >self.bannerArray.count-1) {
        self.index = 0;
    }
    SDAnimatedImageView *tmpImgeview=[self.bannerView viewWithTag:100+self.index];
//    tmpImgeview.currentFrameIndex=0;
    [tmpImgeview stopAnimating];
    [tmpImgeview startAnimating];
    [self.bannerView srollewToindex:self.index];
 
    GYBannerModel *model = (GYBannerModel *)self.bannerArray[self.index];
    NSString *path = [NSString stringWithFormat:@"%@/%@", [GYGlobal gifPath], [model.url lastPathComponent]];
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    if ([fileManager fileExistsAtPath:path]){
        NSTimeInterval time = [GYGlobal durationForGifData:[NSData dataWithContentsOfFile:path]];
        [self afterTime:time];
    }
    
}

#pragma mark  ZYBannerViewDelegate和ZYBannerViewDataSource

-(NSInteger)numberOfItemsInBanner:(ZYBannerView *)banner{
    
    if (self.bannerArray.count>0) {
        return self.bannerArray.count;
    } else {
        return 1;
    }
}

- (UIView *)banner:(ZYBannerView *)banner viewForItemAtIndex:(NSInteger)index {
    
    if (self.bannerArray.count > index) {

        UIView *view=[[UIView alloc] init];
        view.backgroundColor=[UIColor clearColor];
        GYBannerModel *bannerModel = self.bannerArray[index];

        SDAnimatedImageView *tmpImgeview = [[SDAnimatedImageView alloc] initWithFrame:CGRectMake(12*ScaleWidth, 0, self.bannerView.width-24*ScaleWidth, self.bannerView.height)];
        tmpImgeview.tag=100+index;
        [view addSubview:tmpImgeview];
        tmpImgeview.contentMode = UIViewContentModeScaleAspectFill;
        tmpImgeview.clipsToBounds=YES;
        tmpImgeview.animationRepeatCount=1;// gif播放一次,改设置只有在shouldCustomLoopCount = yes时生效
        tmpImgeview.shouldCustomLoopCount=YES;
        tmpImgeview.clearBufferWhenStopped=YES;
        tmpImgeview.resetFrameIndexWhenStopped=YES;
        tmpImgeview.layer.cornerRadius = 8*ScaleWidth;
        NSString *savePath =[bannerModel.url lastPathComponent];
        
        NSString *path = [NSString stringWithFormat:@"%@/%@", [GYGlobal gifPath], savePath];

        NSFileManager *fileManager = [[NSFileManager alloc] init]; 
        if ([fileManager fileExistsAtPath:path]) {
            tmpImgeview.image = [SDAnimatedImage imageWithContentsOfFile:path];
            GYBannerModel *model = (GYBannerModel *)self.bannerArray.firstObject;
            if([[model.url lastPathComponent] isEqualToString:[path lastPathComponent]]) {
                NSTimeInterval time = [GYGlobal durationForGifData:[NSData dataWithContentsOfFile:path]];
                [self afterTime:time];
            }

        }else {
            
            [GYGlobal downloadUrlFontWithUrl:bannerModel.url fileName:savePath response:^(NSString * _Nonnull path, NSError * _Nonnull error) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    tmpImgeview.image=[SDAnimatedImage imageWithContentsOfFile:path];
                    [self toLoadNext:index+1];
                    GYBannerModel *model = (GYBannerModel *)self.bannerArray.firstObject;
                    if([[model.url lastPathComponent] isEqualToString:[path lastPathComponent]]) {
                        NSTimeInterval time = [GYGlobal durationForGifData:[NSData dataWithContentsOfFile:path]];
                        [self afterTime:time];
                    }
                    
                });
            }];
        }
        return view;

    } else {
        UIImageView *tmpImgeview = [[UIImageView alloc] init];
        tmpImgeview.image = [UIImage imageNamed:@"ic_banner_icon"];
        tmpImgeview.contentMode = UIViewContentModeScaleAspectFill;
        return tmpImgeview;
    }
    
}
-(void)toLoadNext:(NSInteger)index
{
    if (self.bannerArray.count > index)
    {
        GYBannerModel *bannerModel = self.bannerArray[index];
        NSString *savePath =[bannerModel.url lastPathComponent];
        NSString *path = [NSString stringWithFormat:@"%@/%@", [GYGlobal gifPath], savePath];
        NSFileManager *fileManager = [[NSFileManager alloc] init];
        if (![fileManager fileExistsAtPath:path]) {
  
            [GYGlobal downloadUrlFontWithUrl:bannerModel.url fileName:savePath response:^(NSString * _Nonnull path, NSError * _Nonnull error) {
               
            }];

        }
    }
    
}
- (void)banner:(ZYBannerView *)banner didScrollToItemAtIndex:(NSInteger)index {
    self.index=index;
    self.pageControl.currentPage = index;
    SDAnimatedImageView *tmpImgeview=[self.bannerView viewWithTag:100+self.index];
//    tmpImgeview.currentFrameIndex=0;
    [tmpImgeview stopAnimating];
    [tmpImgeview startAnimating];
    GYBannerModel *model = (GYBannerModel *)self.bannerArray[self.index];
    NSString *path = [NSString stringWithFormat:@"%@/%@", [GYGlobal gifPath], [model.url lastPathComponent]];
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    if ([fileManager fileExistsAtPath:path]){
        NSTimeInterval time = [GYGlobal durationForGifData:[NSData dataWithContentsOfFile:path]];
        [self afterTime:time];
    }

}
- (void)banner:(ZYBannerView *)banner didSelectItemAtIndex:(NSInteger)index {

    if (self.bannerArray.count>0) {
        GYBannerModel *bannerModel = self.bannerArray[index];

        if([bannerModel.name isEqualToString:@"AI漫画"]) {
            GYChoosePhotoView *view = [GYChoosePhotoView choosePhotoView];
            [view show];
        }else if([bannerModel.name isEqualToString:@"默认"]) {
            GYAIDrawViewController *aidrawVC=[[GYAIDrawViewController alloc] init];
            [[GlobalFunc getCurrentViewController].navigationController pushViewController:aidrawVC animated:YES];
        }

    }
}

#pragma -----------------------------bannerUI层面初始化--------------------
/*
注意在使用ZYBannerView时,一定要注意frame的宽度时屏幕的宽度,否则滑动有问题
*/
- (void)initbanner {
    
    self.bannerView = [[ZYBannerView alloc] initWithFrame:CGRectMake(0, 0, ViewWidth, 110*ScaleWidth)];
//    self.bannerView.layer.masksToBounds = YES;
//    self.bannerView.layer.cornerRadius = 8*ScaleWidth;
    self.bannerView.delegate = self;
    self.bannerView.dataSource = self;
//    self.bannerView.autoScroll = YES;
    self.bannerView.shouldLoop = YES;
    self.bannerView.backgroundColor = [UIColor clearColor];
    self.bannerView.pageControlFrame = CGRectMake(0, 80*ScaleWidth, ViewWidth, 10);
    self.bannerView.pageControl.hidden = YES;
    [self addSubview:self.bannerView];
    
    [self.bannerView addSubview:self.pageControl];

    
}
- (EllipsePageControl *)pageControl {
    
    if (nil == _pageControl) {
        _pageControl = [[EllipsePageControl alloc] init];
        _pageControl.frame=CGRectMake(0, 110*ScaleWidth - 10, ViewWidth-24*ScaleWidth, 4);
        _pageControl.userInteractionEnabled = NO;
        _pageControl.hidden = YES;
        _pageControl.otherColor = rgba(255, 255, 255, 0.40);
        _pageControl.currentColor = rgba(255, 255, 255, 1);
        _pageControl.currentControlSize = CGSizeMake(10, 6);
        _pageControl.controlSpacing = 6;
    }
    return _pageControl;
}
@end

工具类中代码:

//
//  GYGlobal.m
//  GuiYuSiri
//
//  Created by wbb on 2022/12/15.
//

#import "GYGlobal.h"

@implementation GYGlobal
+ (UIViewController *)getCurrentVC {
    UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
    NSAssert(window, @"The window is empty");
    //获取根控制器
    UIViewController* currentViewController = window.rootViewController;
    //获取当前页面控制器
    BOOL runLoopFind = YES;
    while (runLoopFind){
        if (currentViewController.presentedViewController) {
            currentViewController = currentViewController.presentedViewController;
        } else if ([currentViewController isKindOfClass:[UINavigationController class]]) {
            UINavigationController* navigationController = (UINavigationController* )currentViewController;
            currentViewController = [navigationController.childViewControllers lastObject];
        } else if ([currentViewController isKindOfClass:[UITabBarController class]]){
            UITabBarController* tabBarController = (UITabBarController* )currentViewController;
            currentViewController = tabBarController.selectedViewController;
        } else {
            NSUInteger childViewControllerCount = currentViewController.childViewControllers.count;
            if (childViewControllerCount > 0) {
                currentViewController = currentViewController.childViewControllers.lastObject;
                return currentViewController;
            } else {
                return currentViewController;
            }
        }
    }
    return currentViewController;
}

+(void)getWebGifImageWithKey:(NSString*)key response:(void(^)(NSString *path, NSError *error))block {
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
    NSURL *url = [NSURL URLWithString:key];
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
        } else {
            //图片下载已完成,处理数据
        }
        if (block) {
            block(location.path,error);
        }
    }];
    
    [task resume];
}
+ (BOOL)createDir:(NSString *)path {
    NSAssert(path > 0, @"%s: The length of path should be greater than 0.", __FUNCTION__);
    NSFileManager *fileManager = [NSFileManager defaultManager];
    BOOL isSuccess = NO;
    // 判断目录是否已经存在
    if (![fileManager fileExistsAtPath:path]) {
        // 创建文件目录
        NSError *error = nil;
        isSuccess = [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
        if (error) {
            NSLog(@"Create directory failed: %@",[error localizedDescription]);
        }
    }
    return isSuccess;
}
+ (void)downloadUrlFontWithUrl:(NSString *)fontUrl  fileName:(NSString *)fileName response:(void(^)(NSString *path, NSError *error))block {
    [self createDir:[self gifPath]];
    // 下载字体文件
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];
#if (URL_Index==2)
    AFSecurityPolicy * securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    //allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
    //如果是需要验证自建证书,需要设置为YES
    securityPolicy.allowInvalidCertificates = YES;
    //validatesDomainName 是否需要验证域名,默认为YES;
    //假如证书的域名与你请求的域名不一致,需把该项设置为NO
    //主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
    securityPolicy.validatesDomainName = NO;
    //validatesCertificateChain 是否验证整个证书链,默认为YES
    //设置为YES,会将服务器返回的Trust Object上的证书链与本地导入的证书进行对比,这就意味着,假如你的证书链是这样的:
    //GeoTrust Global CA
    //    Google Internet Authority G2
    //        *.google.com
    //那么,除了导入*.google.com之外,还需要导入证书链上所有的CA证书(GeoTrust Global CA, Google Internet Authority G2);
    //如是自建证书的时候,可以设置为YES,增强安全性;假如是信任的CA所签发的证书,则建议关闭该验证;
//    securityPolicy.validatesCertificateChain = NO;
    manager.securityPolicy = securityPolicy;

#endif
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json", @"text/plain", @"text/html",@"image/jpg",@"image/png", nil];
    NSURL *urlpath = [NSURL URLWithString:fontUrl];
    NSURLRequest *request = [NSURLRequest requestWithURL:urlpath];

    NSString *savePath = [NSString stringWithFormat:@"%@/%@", [self gifPath], fileName];
    
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {

        return [NSURL fileURLWithPath:savePath];
        
    } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
        NSString * createFilePath = [filePath path];
//        NSLog(@"下载后的地址-%@",createFilePath);

//        NSString * fontName = [self registerCustomFontWithPath:toPath];

//        if (self.downloadFinishBlock) {
//            self.downloadFinishBlock(fileName);
//        }
        
        if (block) {
            block(createFilePath,error);
        }
    }];
    
    [downloadTask resume];
}
+ (NSString *)gifPath {
    return  [NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/GYGif"]];
}
//获取gif图片的总时长和循环次数
+ (NSTimeInterval)durationForGifData:(NSData *)data{
    //将GIF图片转换成对应的图片源
    CGImageSourceRef gifSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    //获取其中图片源个数,即由多少帧图片组成
    size_t frameCout = CGImageSourceGetCount(gifSource);
    //定义数组存储拆分出来的图片
    NSMutableArray* frames = [[NSMutableArray alloc] init];
    NSTimeInterval totalDuration = 0;
    for (size_t i=0; i<frameCout; i++) {
        //从GIF图片中取出源图片
        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
        //将图片源转换成UIimageView能使用的图片源
        UIImage* imageName = [UIImage imageWithCGImage:imageRef];
        //将图片加入数组中
        [frames addObject:imageName];
        NSTimeInterval duration = [self gifImageDeleyTime:gifSource index:i];
        totalDuration += duration;
        CGImageRelease(imageRef);
    }

   //获取循环次数
    NSInteger loopCount;//循环次数
    CFDictionaryRef properties = CGImageSourceCopyProperties(gifSource, NULL);
    if (properties) {
        CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
        if (gif) {
            CFTypeRef loop = CFDictionaryGetValue(gif, kCGImagePropertyGIFLoopCount);
            if (loop) {
                //如果loop == NULL,表示不循环播放,当loopCount  == 0时,表示无限循环;
                CFNumberGetValue(loop, kCFNumberNSIntegerType, &loopCount);
            };
        }
    }

    CFRelease(gifSource);
    return totalDuration;
}
//获取GIF图片每帧的时长
+ (NSTimeInterval)gifImageDeleyTime:(CGImageSourceRef)imageSource index:(NSInteger)index {
   NSTimeInterval duration = 0;
   CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, NULL);
   if (imageProperties) {
       CFDictionaryRef gifProperties;
       BOOL result = CFDictionaryGetValueIfPresent(imageProperties, kCGImagePropertyGIFDictionary, (const void **)&gifProperties);
       if (result) {
           const void *durationValue;
           if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFUnclampedDelayTime, &durationValue)) {
               duration = [(__bridge NSNumber *)durationValue doubleValue];
               if (duration < 0) {
                   if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFDelayTime, &durationValue)) {
                       duration = [(__bridge NSNumber *)durationValue doubleValue];
                   }
               }
           }
       }
   }
   
   return duration;
}
@end

相关文章

网友评论

      本文标题:iOS gif banner相关问题

      本文链接:https://www.haomeiwen.com/subject/ohcvcdtx.html