摘要: 类似标签云的球状布局,也类似与魔方的3D布局

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;
}

布局效果如下:

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

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

iOS流布局UICollectionView系列七——三维中的球型布局的更多相关文章

  1. iOS流布局UICollectionView使用FlowLayout进行更灵活布局

    一.引言 前面的博客介绍了UICollectionView的相关方法和其协议中的方法,但对布局的管理类UICollectionViewFlowLayout没有着重探讨,这篇博客介绍关于布局的相关设置和 ...

  2. iOS 流布局 UICollectionView使用(使用FlowLayout进行更灵活布局)

    在UICollectionView的布局中,如果每个item的大小都一样那么是十分简单的事情,但是,如果我们想要的每个item大小不一样呢,这个时候,就要对UICollectionViewFlowLa ...

  3. iOS 流布局 UICollectionView使用(简单使用)

    简介 UICollectionView是iOS6之后引入的一个新的UI控件,它和UITableView有着诸多的相似之处,其中许多代理方法都十分类似.简单来说,UICollectionView是比UI ...

  4. Spark系列(七)Master中的资源调度

    资源调度 说明: Application的调度算法有两种,分别为spreadOutApps和非spreadOutApps spreadOutApps 在spark-submit脚本中,可以指定要多少个 ...

  5. iOS 流布局 UICollectionView使用(UICollectionVIew的代理方法)

    UICollectionViewDataSource协议 这个协议主要用于collectionView相关数据的处理,包含方法如下: 设置分区数(这个是可选实现的) - (NSInteger)numb ...

  6. 【iOS系列】-oc中特有的语法

    [iOS系列]-oc中特有的语法 oc数据类型: 1,基本类型 2,对象类型 3,id 4,BOOL 5,block 6,SEL 1:category 使用继承关系来扩充一个类,有一个弊病,高耦合性 ...

  7. Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager)

    Alamofire源码解读系列(七)之网络监控(NetworkReachabilityManager) 本篇主要讲解iOS开发中的网络监控 前言 在开发中,有时候我们需要获取这些信息: 手机是否联网 ...

  8. iOS开发UI篇—iPad开发中得modal介绍

    iOS开发UI篇—iPad开发中得modal介绍 一.简单介绍 说明1: 在iPhone开发中,Modal是一种常见的切换控制器的方式 默认是从屏幕底部往上弹出,直到完全盖住后面的内容为止 说明2: ...

  9. 【转】iOS开发工具系列(按功能分)

    http://www.cocoachina.com/newbie/basic/2014/0417/8187.html 这是我们多篇iOS开发工具系列篇中的一篇,此前的文章比如:那些不能错过的Xcode ...

随机推荐

  1. ubi and ubifs应用手记

    转:http://blog.sina.com.cn/s/blog_5de7d9f80100dpa4.html 1.配置ubi and ubifsin .config  CONFIG_MTD_UBI=y ...

  2. 手动删除SVCH0ST.EXE的方法

        最近几天在办公室的计算机上又发现了一种病毒,在进程管理器中多出了两个进程:SVCH0ST.EXE.IEXPLORE.EXE,经一番查看揭开了它们的真面目,现将清除这种病毒的方法总结如下: 病毒 ...

  3. IP分类:A,B,C,D,E五类

    IP地址分为五类: IP地址分为五类:A类保留给政府机构,B类分配给中等规模的公司,C类分配给任何需要的人,D类用于组播,E类用于实验. 常用的三类IP地址 IP = 网路地址(网络号)+主机地址(主 ...

  4. Qt中的非模式窗口配置;

    Test7_5A::Test7_5A(QWidget *parent) : QMainWindow(parent){ ui.setupUi(this); m_searchwin = new Searc ...

  5. JS中的柯里化及精巧的自动柯里化实现

    一.什么是柯里化? 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由 C ...

  6. 【Zookeeper】Zookeeper 和他的小伙伴们

    ZK实际应用场景.实例:

  7. rsync数据同步工具的配置

    rsync数据同步工具的配置 1. rsync介绍 1.1.什么是rsync rsync是一款开源的快速的,多功能的,可实现全量及增量的本地或远程数据同步备份的优秀工具.Rsync软件适用于 unix ...

  8. Linux学习之二十一-shell编程基础

    Shell编程基础 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言.Shell 是指一种应用程序,这个应用程序提供了一个 ...

  9. 2017.4.12 开涛shiro教程-第十八章-并发登录人数控制

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 开涛shiro教程-第十八章-并发登录人数控制 shiro中没有提 ...

  10. es创建索引的格式,并初始化数据

    es创建索引的格式,并初始化数据 学习了:https://www.imooc.com/video/15759 1, 创建格式 POST 127.0.0.1:9200/book/novel/_mappi ...