模仿IMDb和格瓦拉的图片集混合排布展示效果

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看122 回复回复1 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 122|回复: 1
收起左侧

模仿IMDb和格瓦拉的图片集混合排布展示效果

[复制链接]
代码买卖 发表于 2016-7-28 01:21:35 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑

iMDb和格瓦拉的图片集排布,自己抽时间进行了一次尝试,使用自定义UICollectionViewFlowLayout来进行布局,目前点击事件效果还没有完善。

先看一下iMDb和格瓦拉的图片集排布的效果:

模仿IMDb和格瓦拉的图片集混合排布展示效果 1

模仿IMDb和格瓦拉的图片集混合排布展示效果 - 敏捷大拇指 - 模仿IMDb和格瓦拉的图片集混合排布展示效果 1


模仿IMDb和格瓦拉的图片集混合排布展示效果 2

模仿IMDb和格瓦拉的图片集混合排布展示效果 - 敏捷大拇指 - 模仿IMDb和格瓦拉的图片集混合排布展示效果 2


下面是一张相关计算图,字比较丑,别喷我。

模仿IMDb和格瓦拉的图片集混合排布展示效果 3

模仿IMDb和格瓦拉的图片集混合排布展示效果 - 敏捷大拇指 - 模仿IMDb和格瓦拉的图片集混合排布展示效果 3


下面贴出来自定义布局的.h和.m文件,第一次写,不会使用高端工具,以后会继续加油。有好用的工具,可以推荐给我,在这里感谢大家了。

FJSPicMixCollectionViewLayout.h

[Objective-C] 纯文本查看 复制代码
#import "BQImageModel.h"

@interface FJSPicMixCollectionViewLayout : UICollectionViewFlowLayout

@property (nonatomic,strong)NSMutableArray * modelArray;

@property (nonatomic,assign)BOOL isHeaderRefresh;/**< 区分是上拉加载还是下拉刷新 */

@end



#import "FJSPicMixCollectionViewLayout.h"

@interface FJSPicMixCollectionViewLayout ()

@property (nonatomic,assign)CGFloat contentHeight;/**< 总体高度 */@property (nonatomic,strong)NSMutableArray * attributesArray;/**< 存放所有布局的array *///

@property (nonatomic,assign)NSInteger lastArrayCount;/**< 记录上一次的数组整体个数,为了上拉刷新的时候不需要重新计算之前数组的位置,进行性能优化 */

@end

@implementation FJSPicMixCollectionViewLayout

/* 所以我们的思路是在- (void)prepareLayout;方法中算出所有item的frame,并赋值给当前item的  UICollectionViewLayoutAttributes。用图片的形式比较直观: */

-(void)prepareLayout{ 

   [super prepareLayout];   

 if (self.isHeaderRefresh) {       

 //初始化保存所有item attributes的数组      

  self.attributesArray = [NSMutableArray array];        

self.contentHeight = 0.f;//新添加  

  }   

 [self getwholeRowFrame];

}

- (void)getwholeRowFrame{   

 //设置一个宽度来记录和判断图片是否换行.   

 CGFloat width = 0.f;   

 //保存同一行图片的所有尺寸比例和,用来计算这一行图片的高度   

 CGFloat scaleSum = 0.f;   

 //如果之前的布局数组中有数据,上拉加载就从下一行,新来的model开始计算,不需要考虑之前最后一行是否已经超出屏幕,正常是要从倒数第一行重新计算,但是图片可能会有所闪动,体验不好.    

NSInteger beginIndex = self.attributesArray.count?self.attributesArray.count:0;  

  NSInteger currentIndex = beginIndex;    

//不需要担心最后如果只有一张图的话,没有匹配如何显示,因为遍历的次数和图片的数量相同.    NSLog(@"beginIndex == %ld",beginIndex);   

 for (NSInteger i = beginIndex; i < self.modelArray.count; i++) {  

      BQImageModel * model = [self.modelArray objectAtIndex:i];     

   width = width + model.width;     

   scaleSum = scaleSum + model.whScale;  

      //换行之后需要重新清空累计的宽度 同时保存下一个currentIndex从第几行开始.     

   //累计图片宽度,如果宽度超过了屏宽减去间距,则换行(这种方式存在一定的问题,依赖于图片的原始高度来进行排布,不过服务器没法根据客户端来进行图片匹配,所以继续研究了格瓦拉之后,找到了它有一个图片最大高度,即屏幕的一半,所以采用比例和的方式来进行约束.)      

  if (scaleSum >= 2.0) {         

   [self setAttributesFromCurrentIndex:currentIndex DestionIndex:i scaleSum:scaleSum];            //换行之后需要重新清空累计的宽度 同时保存下一个currentIndex从第几行开始.        

    width = 0.f;          

  scaleSum = 0.f;            

currentIndex = i + 1;        

}else        {         

   //如果是最后一行并没有满足超过屏宽,则将当前几个视图进行计算,铺满屏幕   

         if (i == self.modelArray.count - 1) {       

         [self setAttributesFromCurrentIndex:currentIndex DestionIndex:i scaleSum:scaleSum];          }        }    }    }

- (void)setAttributesFromCurrentIndex:(NSInteger)currnetIndex DestionIndex:(NSInteger)destionIndex scaleSum:(CGFloat)scaleSum{   

 //根据公式计算出该行的高度   

 CGFloat height = (ScreenWidth - (destionIndex - currnetIndex) * self.minimumInteritemSpacing) / scaleSum;  

  //均分的宽度,注意:四舍五入成整数   

 height = roundf(height);  

  NSLog(@"从第%ld个到第%ld个,高度为%f",currnetIndex,destionIndex,height);   

 for (NSInteger i = currnetIndex; i <= destionIndex; i++) {       

 //给attributes.frame 赋值,并存入 self.itemsAttributes      

  BQImageModel * model = [self.modelArray objectAtIndex:i];        //根据计算出来的高度来根据图片比例计算出宽度      

  CGFloat width = height * model.whScale;       

 UICollectionViewLayoutAttributes * oldAttributes;     

   /*如果不是这一行的第一个图片,需要获取上一张图片的UICollectionViewLayoutAttributes,用来计算当前的图片的x值.为什么不使用        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];        UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];方法来获取上一个内容呢?因为内容为空,都保存到数组self.attributesArray中了,所以直接获取.        */      

  if (i > currnetIndex) {          

  NSInteger oldIndex = i - 1;           

 oldAttributes = [self.attributesArray objectAtIndex:oldIndex];     

   }       

 NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];        UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];       

 /*获取当前的对应UICollectionViewLayoutAttributes,进行修改,然后保存到数组中        x: 根据同一行,前一个视图进行累计,同时加上self.minimumInteritemSpacing        y: 使用全局的属性记录.        width和height都有计算好了.        */     

   CGFloat orignX = oldAttributes?CGRectGetMaxX(oldAttributes.frame) + self.minimumInteritemSpacing:0;      

  if (destionIndex == currnetIndex && self.modelArray.count - 1 == currnetIndex && model.whScale < 2.0) {        

    attributes.frame = CGRectMake(orignX, self.contentHeight, ScreenWidth, ScreenWidth * 0.5);            height = ScreenWidth * 0.5;     

   }else        {           

 attributes.frame = CGRectMake(orignX, self.contentHeight, width, height);    

    }        

//        NSLog(@"oldAttributes == %f\nself.contentHeight == %f\nwidth == %f\nheight == %f",CGRectGetMaxX(oldAttributes.frame),self.contentHeight,width,height);     

   //        NSLog(@"第%ld个到第%ld个在一行",currnetIndex,destionIndex);        [self.attributesArray addObject:attributes]; 

   }    

//累加记录高度的  

  self.contentHeight = self.contentHeight + height + self.minimumLineSpacing;}-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect

{

NSLog(@"我触发了");

NSLog(@"%ld",self.attributesArray.count);

return self.attributesArray;

}

-(CGSize)collectionViewContentSize{  

  //使用数组中最后一个布局来进行滚动内容的高度,而不是self.contentHeight,原因是需要判断是否是最后一个图片的那一行,如果是不需要累加self.minimumLineSpacing.    UICollectionViewLayoutAttributes * lastAttributes = [self.attributesArray lastObject];        return CGSizeMake(ScreenWidth, CGRectGetMaxY(lastAttributes.frame));}

//#pragma mark -- 返回collectionView的内容的尺寸//-(CGSize)collectionViewContentSize//{////}

#pragma mark -- UICollectionViewLayoutAttributes可以是cell,追加视图或装饰视图的信息,通过不同的UICollectionViewLayoutAttributes初始化方法可以得到不同类型的UICollectionViewLayoutAttributes:

#pragma mark -- 返回对应于indexPath的位置的cell的布局属性

//-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath

//{

//

//}

//

#pragma mark -- 返回对应于indexPath的位置的追加视图的布局属性,如果没有追加视图可不重载

//-(UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath

//{

//

//}

//

#pragma mark -- 返回对应于indexPath的位置的装饰视图的布局属性,如果没有装饰视图可不重载

//-(UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath

//{

//

//}

//

//-(UICollectionViewLayoutAttributes *)layoutAttributesForInteractivelyMovingItemAtIndexPath:(NSIndexPath *)indexPath withTargetPosition:(CGPoint)position

//{

//

//}

/*

- 当边界发生改变时,是否应该刷新布局。如果YES则在边界变化(一般是scroll到其他地方)时,将重新计算需要的布局信息。

另外需要了解的是,在初始化一个UICollectionViewLayout实例后,会有一系列准备方法被自动调用,以保证layout实例的正确。

首先,-(void)prepareLayout将被调用,默认下该方法什么没做,但是在自己的子类实现中,一般在该方法中设定一些必要的layout的结构和初始需要的参数等。

之后,-(CGSize) collectionViewContentSize将被调用,以确定collection应该占据的尺寸。注意这里的尺寸不是指可视部分的尺寸,而应该是所有内容所占的尺寸。collectionView的本质是一个scrollView,因此需要这个尺寸来配置滚动行为。

接下来-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect被调用,这个没什么值得多说的。初始的layout的外观将由该方法返回的UICollectionViewLayoutAttributes来决定。

另外,在需要更新layout时,需要给当前layout发送 -invalidateLayout,该消息会立即返回,并且预约在下一个loop的时候刷新当前layout,这一点和UIView的setNeedsLayout方法十分类似。在-invalidateLayout后的下一个collectionView的刷新loop中,又会从prepareLayout开始,依次再调用-collectionViewContentSize和-layoutAttributesForElementsInRect来生成更新后的布局。

*/

//-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds

//{

//    return YES;

//}

@end


更多的布局方式,再慢慢地添加,有需要你可以在这里获取到整个项目。

https://github.com/BestJoker/FJSPicMixCollectionViewLayout.git

如果对你的思路有一定的帮助,请别吝啬你的星星,预祝大家编程愉快。




相关内容

iOS视觉差Parallax效果简析

模仿IMDb和格瓦拉的图片集混合排布展示效果





作者:BestJoker

都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

嗯,不错!期待更多好内容,支持一把:
支持敏捷大拇指,用支付宝支付10.24元 支持敏捷大拇指,用微信支付10.24元

评分

参与人数 1金钱 +10 收起 理由
Anewczs + 10 推送上首页了~分享到朋友圈微博QQ空间吧~.

查看全部评分

本帖被以下淘专辑推荐:

女汉子 发表于 2016-7-30 02:51:03 | 显示全部楼层
跟瀑布流什么区别~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

做任务,领红包。
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表