做过瀑布流的都清楚,,后台数据会返回图片的宽高,,经过比例处理会整齐的排列。。collectionview的加载图片的过程是先全部设置好没个item的高度,,添加占位图片,,sdwebimage下载图片,,下载完成显示在对应的imageView,,那么后台不返回尺寸该怎么办??有的demo是在数据处理的时候将图片下载下来,获取尺寸,添加进model里。。在collectionview刷新的时候再给item的尺寸,,这样做可以。。但会比较耗时。。有图片缓存还好,,如果是上拉加载新的图片。。用户体验会特别的差。你就等吧。
与后台沟通后 结果是图片太多了 取尺寸太麻烦,,前台想办法。。。。。
安卓和iOS 都采用了同一个思路 先给一个固定相同的高度,,线程获取图片尺寸,,获取结束后,再刷新高度,,虽然用户体验也极差,,会看到图片突然地变大或变小。。但没找到更好的办法。。下面是我的APP用到的关键代码
#pragma mark 加载数据
- (void)addData{
__weakTuiJianViewController *weakSelf =self;
dispatch_async(dispatch_get_global_queue(0,0), ^{
[[CommuncationsharedInstance] loadShouYeTuiJianWithstart:requestStartlimit:limitsucess:^(id result) {
/// 断网的情况请求出错时走缓存数据
if ([resultisKindOfClass:[NSErrorclass]]) {
self.imagewarr = [NSMutableArrayarray];
self.imageharr = [NSMutableArrayarray];
requestResultArray = [NSMutableArrayarray];
requestResultArray = [NSKeyedUnarchiverunarchiveObjectWithFile:[PathToolthePath:@"TuiJianData"]];
for (NSDictionary *bodyin requestResultArray) {
NSString *imageUrl = imageUrl = body[@"video"][@"cover"];
/// 获取图片尺寸的方法,,有缓存从缓存中获取
CGSize size = [ImageSizeTool downloadImageSizeWithURL:[NSURLURLWithString:[NSStringstringWithFormat:@"%@%@",URLADDRESS,imageUrl]]];
[self.imagewarraddObject:[NSStringstringWithFormat:@"%f",size.width]];
[self.imageharraddObject:[NSStringstringWithFormat:@"%f",size.height]];
}
[weakSelf.tuijianCollectionViewreloadData];
[weakSelf.tuijianCollectionView.mj_footerendRefreshing];
[weakSelf.tuijianCollectionView.mj_headerendRefreshing];
}else{
if (!result[@"state"]) {
if (result[@"customMessage"]) {
[[iToastmakeText:result[@"customMessage"]]show];
}
}else{
NSInteger num =requestStart;
requestStart =requestStart + [result[@"body"]count];
self.imagearr = [NSMutableArrayarray];
for (NSDictionary *bodyin result[@"body"]) {
if (![requestResultArraycontainsObject:body]) {
[requestResultArrayaddObject:body];
}
NSString *imageUrl = body[@"live"][@"cover"];
[self.imagearraddObject:imageUrl];
// 获取图片尺寸之前 先设置固定相同的尺寸 添加进宽高尺寸数组,,在你的瀑布流高度返回方法里进行按比例缩 放,,设置瀑布流的高度
[self.imageharraddObject:@"500"];
[self.imagewarraddObject:@"900"];
[SVProgressHUD dismiss];
}
// 进行缓存 、、、、 这里的缓存是为断网情况有数据 ,,不是图片的缓存
[NSKeyedArchiverarchiveRootObject:requestResultArraytoFile:[PathToolthePath:@"TuiJianData"]];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.tuijianCollectionViewreloadData];
/// 回到主线程获取图片的尺寸
[selfjisun:self.imagearrnsinteger:num];
[weakSelf.tuijianCollectionView.mj_footerendRefreshing];
[weakSelf.tuijianCollectionView.mj_headerendRefreshing];
});
[SVProgressHUDdismiss];
}
}
}];
});
}
- (void)jisun:(NSMutableArray *)arr nsinteger:(NSInteger)nsinteger{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
// 耗时的操作
for (NSInteger i =0; i<arr.count; i++) {
CGSize size = [ImageSizeTooldownloadImageSizeWithURL:[NSURLURLWithString:[NSStringstringWithFormat:@"%@%@",URLADDRESS,arr[i]]]];
// 因为之前设置了相同的固定的尺寸 在这里获取到后进行替换
[self.imagewarrreplaceObjectAtIndex:nsinteger + iwithObject:[NSStringstringWithFormat:@"%f",size.width]];
[self.imageharrreplaceObjectAtIndex:nsinteger + iwithObject:[NSStringstringWithFormat:@"%f",size.height]];
}
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面 尺寸获取后再刷新一遍
[self.tuijianCollectionViewreloadData];
});
});
}
获取尺寸方法 来自网络 先从缓存中找 没有再网络获取 可以节省时间
+(CGSize)downloadImageSizeWithURL:(id)imageURL {
NSURL* URL =nil;
if([imageURLisKindOfClass:[NSURLclass]]){
URL = imageURL;
}
if([imageURLisKindOfClass:[NSStringclass]]){
URL = [NSURLURLWithString:imageURL];
}
if(URL ==nil)
returnCGSizeZero;
NSString* absoluteString = URL.absoluteString;
#ifdef dispatch_main_sync_safe 从缓存中获取
if([[SDImageCachesharedImageCache] diskImageExistsWithKey:absoluteString]){
UIImage* image = [[SDImageCachesharedImageCache] imageFromMemoryCacheForKey:absoluteString];
if(!image){
NSData* data = [[SDImageCachesharedImageCache] performSelector:@selector(diskImageDataBySearchingAllPathsForKey:)withObject:URL.absoluteString];
image = [UIImageimageWithData:data];
}
if(image){
return image.size;
}
}
#endif 从网络获取
NSMutableURLRequest *request = [[NSMutableURLRequestalloc] initWithURL:URL];
NSString* pathExtendsion = [URL.pathExtensionlowercaseString];
CGSize size =CGSizeZero;
if([pathExtendsionisEqualToString:@"png"]){
size = [selfdownloadPNGImageSizeWithRequest:request];
}elseif([pathExtendsionisEqual:@"gif"]){
size = [selfdownloadGIFImageSizeWithRequest:request];
}else{
size = [selfdownloadJPGImageSizeWithRequest:request];
}
if(CGSizeEqualToSize(CGSizeZero, size)){
NSData* data = [NSURLConnectionsendSynchronousRequest:[NSURLRequestrequestWithURL:URL] returningResponse:nilerror:nil];
UIImage* image = [UIImageimageWithData:data];
if(image){
#ifdef dispatch_main_sync_safe
[[SDImageCachesharedImageCache] storeImage:image recalculateFromImage:YESimageData:data forKey:URL.absoluteStringtoDisk:YES];
#endif
size = image.size;
}
}
return size;
}
+(CGSize)downloadPNGImageSizeWithRequest:(NSMutableURLRequest*)request{
[request setValue:@"bytes=16-23"forHTTPHeaderField:@"Range"];
NSData* data = [NSURLConnectionsendSynchronousRequest:requestreturningResponse:nilerror:nil];
if(data.length ==8){
int w1 =0, w2 = 0, w3 =0, w4 = 0;
[data getBytes:&w1range:NSMakeRange(0,1)];
[data getBytes:&w2range:NSMakeRange(1,1)];
[data getBytes:&w3range:NSMakeRange(2,1)];
[data getBytes:&w4range:NSMakeRange(3,1)];
int w = (w1 <<24) + (w2 << 16) + (w3 <<8) + w4;
int h1 =0, h2 = 0, h3 =0, h4 = 0;
[data getBytes:&h1range:NSMakeRange(4,1)];
[data getBytes:&h2range:NSMakeRange(5,1)];
[data getBytes:&h3range:NSMakeRange(6,1)];
[data getBytes:&h4range:NSMakeRange(7,1)];
int h = (h1 <<24) + (h2 << 16) + (h3 <<8) + h4;
returnCGSizeMake(w, h);
}
returnCGSizeZero;
}
+(CGSize)downloadGIFImageSizeWithRequest:(NSMutableURLRequest*)request{
[request setValue:@"bytes=6-9"forHTTPHeaderField:@"Range"];
NSData* data = [NSURLConnectionsendSynchronousRequest:requestreturningResponse:nilerror:nil];
if(data.length ==4){
short w1 =0, w2 = 0;
[data getBytes:&w1range:NSMakeRange(0,1)];
[data getBytes:&w2range:NSMakeRange(1,1)];
short w = w1 + (w2 <<8);
short h1 =0, h2 = 0;
[data getBytes:&h1range:NSMakeRange(2,1)];
[data getBytes:&h2range:NSMakeRange(3,1)];
short h = h1 + (h2 <<8);
returnCGSizeMake(w, h);
}
returnCGSizeZero;
}
+(id)diskImageDataBySearchingAllPathsForKey:(id)key{returnnil;}
+(CGSize)downloadJPGImageSizeWithRequest:(NSMutableURLRequest*)request{
[request setValue:@"bytes=0-209"forHTTPHeaderField:@"Range"];
NSData* data = [NSURLConnectionsendSynchronousRequest:requestreturningResponse:nilerror:nil];
if ([datalength] <= 0x58) {
returnCGSizeZero;
}
if ([datalength] < 210) {//肯定只有一个DQT字段
short w1 =0, w2 = 0;
[data getBytes:&w1range:NSMakeRange(0x60,0x1)];
[data getBytes:&w2range:NSMakeRange(0x61,0x1)];
short w = (w1 <<8) + w2;
short h1 =0, h2 = 0;
[data getBytes:&h1range:NSMakeRange(0x5e,0x1)];
[data getBytes:&h2range:NSMakeRange(0x5f,0x1)];
short h = (h1 <<8) + h2;
returnCGSizeMake(w, h);
} else {
short word =0x0;
[data getBytes:&wordrange:NSMakeRange(0x15,0x1)];
if (word ==0xdb) {
[data getBytes:&wordrange:NSMakeRange(0x5a,0x1)];
if (word ==0xdb) {//两个DQT字段
short w1 =0, w2 = 0;
[data getBytes:&w1range:NSMakeRange(0xa5,0x1)];
[data getBytes:&w2range:NSMakeRange(0xa6,0x1)];
short w = (w1 <<8) + w2;
short h1 =0, h2 = 0;
[data getBytes:&h1range:NSMakeRange(0xa3,0x1)];
[data getBytes:&h2range:NSMakeRange(0xa4,0x1)];
short h = (h1 <<8) + h2;
returnCGSizeMake(w, h);
} else {//一个DQT字段
short w1 =0, w2 = 0;
[data getBytes:&w1range:NSMakeRange(0x60,0x1)];
[data getBytes:&w2range:NSMakeRange(0x61,0x1)];
short w = (w1 <<8) + w2;
short h1 =0, h2 = 0;
[data getBytes:&h1range:NSMakeRange(0x5e,0x1)];
[data getBytes:&h2range:NSMakeRange(0x5f,0x1)];
short h = (h1 <<8) + h2;
returnCGSizeMake(w, h);
}
} else {
returnCGSizeZero;
}
}
}
下面是一个大神用SDWebImage 实现的瀑布流 github地址:https://github.com/songhailiang/DynamicWaterfall