人一切的痛苦,本質上都是對自己的無能的憤怒。
上篇文章 http://www.lxweimin.com/p/cbae7317e41e 已經對UICollectionView進行了最基本的介紹,本次就搭配Photos框架介紹一個比較常見的圓形布局,以展示UICollectionView是如何進行自定義布局的
目錄
UICollectionViewLayoutAttributes 基本介紹
自定義UICollectionViewLayout
Photos基本介紹及使用
UICollectionViewLayoutAttributes 基本介紹
- UICollectionViewLayoutAttributes 屬性
@property (nonatomic) CGRect frame //邊框
@property (nonatomic) CGPoint center //中心點
@property (nonatomic) CGSize size //大小
@property (nonatomic) CATransform3D transform3D //形狀
@property (nonatomic) CGFloat alpha //透明度
@property (nonatomic) NSInteger zIndex //層級關系
@property (nonatomic, getter=isHidden) BOOL hidden //是否影藏
UICollectionViewLayoutAttributes屬性中包括了大小,中心,形狀,透明度等一些屬性,cell的位置已經屬性就是通過他來設置的。
每個cell對應一個UICollectionViewLayoutAttributes。
自定義UICollectionViewLayout
-(CGSize)collectionViewContentSize
//返回collectionView的內容的尺寸
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
/*返回rect中的所有的元素的布局屬性
返回的是包含UICollectionViewLayoutAttributes的NSArray
UICollectionViewLayoutAttributes可以是cell,追加視圖或裝飾視圖的信息,通過不同的UICollectionViewLayoutAttributes初始化方法可以得到不同類型的UICollectionViewLayoutAttributes:
layoutAttributesForCellWithIndexPath:
layoutAttributesForSupplementaryViewOfKind:withIndexPath:
layoutAttributesForDecorationViewOfKind:withIndexPath:
*/
-(UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath
//返回對應于indexPath的位置的cell的布局屬性
-(UICollectionViewLayoutAttributes )layoutAttributesForSupplementaryViewOfKind:(NSString )kind atIndexPath:(NSIndexPath *)indexPath
//返回對應于indexPath的位置的追加視圖的布局屬性,如果沒有追加視圖可不重載
-(UICollectionViewLayoutAttributes * )layoutAttributesForDecorationViewOfKind:(NSString)decorationViewKind atIndexPath:(NSIndexPath )indexPath
//返回對應于indexPath的位置的裝飾視圖的布局屬性,如果沒有裝飾視圖可不重載
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
//當邊界發生改變時,是否應該刷新布局。如果YES則在邊界變化(一般是scroll到其他地方)時,將重新計算需要的布局信息。
- 我們知道,UIControllerView是通過collectionViewLayout來實現布局的,因此我們要自定義布局就必須自定義一個layout繼承自UICollectionViewLayout
//CircleLayout 是繼承自 UICollectionViewLayout 的
CircleLayout * layout = [[CircleLayout alloc]init];
我們在實例化這個layout之后,系統會進行一些準備工作,首先就會調用-(void)prepareLayout方法,這個方法在默認情況下是什么也沒做的,但是我們在自定義的layout中會進行一些參數的設置。
整體的調用順序是 prepareLayout --> collectionViewContentSize --> layoutAttributesForElementsInRect
需要更新布局時,調用 invalidateLayout 會立刻返回,并且預約在下一個 loop 時重新進行上面這個方法的順序調用
自定義的 layout (圓形布局)
{
NSMutableArray<UICollectionViewLayoutAttributes *> * _attributeAttay;
int _itemCount; //item 個數
}
- (void)prepareLayout
{
[super prepareLayout];
//獲取item的個數
_itemCount = (int)[self.collectionView numberOfItemsInSection:0];
_attributeAttay = [[NSMutableArray alloc]init];
//先設定大圓的半徑 取長和寬最短的
CGFloat radius = MIN(self.collectionView.frame.size.width, self.collectionView.frame.size.height)/2;
//計算圓心位置
CGPoint center = CGPointMake(self.collectionView.frame.size.width/2, self.collectionView.frame.size.height/2);
//設置每個item的大小為50*50 則半徑為25
for (int i=0; i<_itemCount; i++) {
UICollectionViewLayoutAttributes * attris = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
//設置item大小
attris.size = CGSizeMake(100, 100);
//計算每個item的圓心位置
//算出的x y值還要減去item自身的半徑大小
float x = center.x+cosf(2*M_PI/_itemCount*i)*(radius-50);
float y = center.y+sinf(2*M_PI/_itemCount*i)*(radius-50);
attris.center = CGPointMake(x, y);
[_attributeAttay addObject:attris];
}
}
//設置內容區域的大小
-(CGSize)collectionViewContentSize{
return self.collectionView.frame.size;
}
//返回設置數組
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
return _attributeAttay;
}
Photos基本介紹及使用
- 在 iOS8.0 之前使用的是 AssetsLibrary 框架,iOS8.0之后改為Photos框架了。
- **本期只進行最基本的使用,就是獲取相冊中的照片,并展示。詳細的,如保存照片到照片庫,修改等下期進行詳細的介紹 **
- PHFetchResult 其實就是所有的照片,里面放的是 一個個 PHAsset ,而 PHAsset 其實就是一張照片的詳細信息,包括拍攝時間啊,地點啊,相機啊等這些。當然還有照片本身
通過懶加載來初始化 PHFetchResult
- (PHFetchResult *)assets
{
if (_assets == nil) {
_assets = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];
}
return _assets;
}
PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
//在速度與質量中選擇
option.resizeMode = PHImageRequestOptionsResizeModeFast;
option.synchronous = NO;
option.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize screenSize = [UIScreen mainScreen].bounds.size;
typeof(self)weakSelf = self;
// 整個相冊通過 PHImageManager 單例來管理
// 這個方法就是用來獲取照片的
[[PHImageManager defaultManager] requestImageForAsset:weakSelf.assets[indexPath.row] targetSize:CGSizeMake(screenSize.width*scale, screenSize.height*scale) contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
//結果 result 就包含照片的信息
cell.imageView.image = [UIImage imageWithData:UIImageJPEGRepresentation(result, 0.5)];
cell.localIdentifier = weakSelf.assets[indexPath.row].localIdentifier;
}];
- 將獲得的圖片展示到cell上,就完成了照片的基本獲取和展示了
** 注意:在iOS 10之后,要在plist文件中添加Privacy - Photo Library Usage Description 這個鍵才能訪問相冊,否則會崩潰!
**
以上就是對 UICollectionView 圓形布局的基本實現,以及Photos框架的基本使用,如果你在實現的過程中,有任何問題,歡迎在評論區留言,我會盡快回復。謝謝觀看!