iOS流布局UICollectionView系列七——三维中的球型布局

简介: iOS流布局UICollectionView系列七——三维中的球型布局

iOS流布局UICollectionView系列七——三维中的球型布局


一、引言


       通过6篇的博客,从平面上最简单的规则摆放的布局,到不规则的瀑布流布局,再到平面中的圆环布局,我们突破了线性布局的局限,在后面,我们将布局扩展到了空间,在Z轴上进行了平移,我们实现了一个类似UIPickerView的布局模型,其实我们还可以再进一步,类比于平面布局,picKerView只是线性排列布局在空间上的旋转与平移,这次,我们更加充分了利用一下空间的尺寸,来设计一个圆球的布局模型。以下是前几篇博客地址:


1.初识与简单实用UICollectionView:http://my.oschina.net/u/2340880/blog/522613


2.UICollectionView的代理方法:http://my.oschina.net/u/2340880/blog/522682


3.实用FlowLayout进行更灵活布局:http://my.oschina.net/u/2340880/blog/522748


4.自定义FlowLayout进行瀑布流布局:http://my.oschina.net/u/2340880/blog/522806


5.平面圆环布局的实现:http://my.oschina.net/u/2340880/blog/523064


6.将布局从平面应用到空间:http://my.oschina.net/u/2340880/blog/523341


二、将布局扩展为空间球型


       在viewController中先实现一些准备代码:


- (void)viewDidLoad {

   [super viewDidLoad];

   // Do any additional setup after loading the view, typically from a nib.

   MyLayout * layout = [[MyLayout alloc]init];

    UICollectionView * collect  = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, 320, 400) collectionViewLayout:layout];

   collect.delegate=self;

   collect.dataSource=self;

   //这里设置的偏移量是为了无缝进行循环的滚动,具体在上一篇博客中有解释

   collect.contentOffset = CGPointMake(320, 400);

   [collect registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellid"];

   [self.view addSubview:collect];

}


-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{

   return 1;

}

//我们返回30的标签

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

   return 30;

}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

   UICollectionViewCell * cell  = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellid" forIndexPath:indexPath];

   cell.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];

   UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 30, 30)];

   label.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];

   [cell.contentView addSubview:label];

   return cell;

}


- (void)didReceiveMemoryWarning {

   [super didReceiveMemoryWarning];

   // Dispose of any resources that can be recreated.

}

//这里对滑动的contentOffset进行监控,实现循环滚动

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{

   if (scrollView.contentOffset.y<200) {

       scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentOffset.y+10*400);

   }else if(scrollView.contentOffset.y>11*400){

       scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentOffset.y-10*400);

   }

   if (scrollView.contentOffset.x<160) {

       scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x+10*320,scrollView.contentOffset.y);

   }else if(scrollView.contentOffset.x>11*320){

       scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x-10*320,scrollView.contentOffset.y);

   }

}


这里面的代码比较上一篇博客中的并没有什么大的改动,只是做了横坐标的兼容。


在我们的layout类中,将代码修改成如下:


-(void)prepareLayout{

   [super prepareLayout];

 

}

//返回的滚动范围增加了对x轴的兼容

-(CGSize)collectionViewContentSize{

   return CGSizeMake( self.collectionView.frame.size.width*([self.collectionView numberOfItemsInSection:0]+2), self.collectionView.frame.size.height*([self.collectionView numberOfItemsInSection:0]+2));

}

-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{

   return YES;

}


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

   UICollectionViewLayoutAttributes * atti = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

   //获取item的个数

   int itemCounts = (int)[self.collectionView numberOfItemsInSection:0];

   atti.center = CGPointMake(self.collectionView.frame.size.width/2+self.collectionView.contentOffset.x, self.collectionView.frame.size.height/2+self.collectionView.contentOffset.y);

   atti.size = CGSizeMake(30, 30);

 

   CATransform3D trans3D = CATransform3DIdentity;

   trans3D.m34 = -1/900.0;

 

   CGFloat radius = 15/tanf(M_PI*2/itemCounts/2);

   //根据偏移量 改变角度

   //添加了一个x的偏移量

   float offsety = self.collectionView.contentOffset.y;

   float offsetx = self.collectionView.contentOffset.x;

   //分别计算偏移的角度

   float angleOffsety = offsety/self.collectionView.frame.size.height;

   float angleOffsetx = offsetx/self.collectionView.frame.size.width;

   CGFloat angle1 = (float)(indexPath.row+angleOffsety-1)/itemCounts*M_PI*2;

   //x,y的默认方向相反

   CGFloat angle2 = (float)(indexPath.row-angleOffsetx-1)/itemCounts*M_PI*2;

   //这里我们进行四个方向的排列

  if (indexPath.row%4==1) {

       trans3D = CATransform3DRotate(trans3D, angle1, 1.0,0, 0);

   }else if(indexPath.row%4==2){

       trans3D = CATransform3DRotate(trans3D, angle2, 0, 1, 0);

   }else if(indexPath.row%4==3){

       trans3D = CATransform3DRotate(trans3D, angle1, 0.5,0.5, 0);

   }else{

       trans3D = CATransform3DRotate(trans3D, angle1, 0.5,-0.5,0);

   }

 

   trans3D = CATransform3DTranslate(trans3D, 0, 0, radius);

 

   atti.transform3D = trans3D;

   return atti;

}



-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{

   NSMutableArray * attributes = [[NSMutableArray alloc]init];

   //遍历设置每个item的布局属性

   for (int i=0; i<[self.collectionView numberOfItemsInSection:0]; i++) {

       [attributes addObject:[self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]];

   }

   return attributes;

}


布局效果如下:


image.png


滑动屏幕,这个圆球是可以进行滚动的。


TIP:这里我们只平均分配了四个方向上的布局,如果item更加小也更加多,我们可以分配到更多的方向上,使球体更加充实。

目录
相关文章
|
2月前
|
安全 iOS开发
iOS页面布局:UIScrollView的布局问题
iOS页面布局:UIScrollView的布局问题
56 8
|
Swift iOS开发
iOS 用一个布局来解决嵌套问题—— UICollectionViewCompositionalLayout
iOS 用一个布局来解决嵌套问题—— UICollectionViewCompositionalLayout
iOS 用一个布局来解决嵌套问题—— UICollectionViewCompositionalLayout
|
iOS开发
iOS布局中的抗被拉伸、抗压缩优先级
iOS布局中的抗被拉伸、抗压缩优先级
658 0
|
iOS开发
IOS15上纯代码布局之导航控制器的导航条为透明的问题
IOS15上纯代码布局之导航控制器的导航条为透明的问题
223 0
|
iOS开发
IOS使用纯代码布局替换掉默认的storyboard
IOS使用纯代码布局替换掉默认的storyboard
103 0
|
iOS开发
iOS第三方左对齐布局类——UICollectionViewLeftAlignedLayout
iOS第三方左对齐布局类——UICollectionViewLeftAlignedLayout
485 0
|
30天前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
98 1
|
1月前
|
设计模式 安全 Swift
探索iOS开发:打造你的第一个天气应用
【9月更文挑战第36天】在这篇文章中,我们将一起踏上iOS开发的旅程,从零开始构建一个简单的天气应用。文章将通过通俗易懂的语言,引导你理解iOS开发的基本概念,掌握Swift语言的核心语法,并逐步实现一个具有实际功能的天气应用。我们将遵循“学中做,做中学”的原则,让理论知识和实践操作紧密结合,确保学习过程既高效又有趣。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你打开一扇通往iOS开发世界的大门。
|
1月前
|
搜索推荐 IDE API
打造个性化天气应用:iOS开发之旅
【9月更文挑战第35天】在这篇文章中,我们将一起踏上iOS开发的旅程,通过创建一个个性化的天气应用来探索Swift编程语言的魅力和iOS平台的强大功能。无论你是编程新手还是希望扩展你的技能集,这个项目都将为你提供实战经验,帮助你理解从构思到实现一个应用的全过程。让我们开始吧,构建你自己的天气应用,探索更多可能!
61 1
|
2月前
|
IDE Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【9月更文挑战第27天】在移动应用开发的世界中,Android和iOS是两个主要的操作系统平台。每个系统都有其独特的开发环境、工具和用户群体。本文将深入探讨这两个平台的关键差异点,并分析这些差异如何影响应用的性能、用户体验和最终的市场表现。通过对比分析,我们将揭示选择正确的开发平台对于确保项目成功的重要作用。