这样一个需求,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
网友评论