經過6篇的博客,從平面上最簡單的規則擺放的佈局,到不規則的瀑布流佈局,再到平面中的圓環佈局,咱們突破了線性佈局的侷限,在後面,咱們將佈局擴展到了空間,在Z軸上進行了平移,咱們實現了一個相似UIPickerView的佈局模型,其實咱們還能夠再進一步,類比於平面佈局,picKerView只是線性排列布局在空間上的旋轉與平移,此次,咱們更加充分了利用一下空間的尺寸,來設計一個圓球的佈局模型。如下是前幾篇博客地址:dom
1.初識與簡單實用UICollectionView:http://my.oschina.net/u/2340880/blog/522613佈局
2.UICollectionView的代理方法:http://my.oschina.net/u/2340880/blog/522682spa
3.實用FlowLayout進行更靈活佈局:http://my.oschina.net/u/2340880/blog/522748.net
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/523341code
在viewController中先實現一些準備代碼:orm
- (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); } }
這裏面的代碼比較上一篇博客中的並無什麼大的改動,只是作了橫座標的兼容。blog
在咱們的layout類中,將代碼修改爲以下:get
-(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更加小也更加多,咱們能夠分配到更多的方向上,使球體更加充實。
專一技術,熱愛生活,交流技術,也作朋友。
——琿少 QQ羣:203317592