- 組頭、組尾
- item的重排問題
- sectionInset內(nèi)邊距
- 自定義Layout
- 第三方CHTCollectionViewWaterfallLayout的使用
組頭、組尾
//每段的段頭視圖,或者段尾視圖
-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
HJCollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"headerView" forIndexPath:indexPath];
SWPWikiModel *wikiModel = self.dataSourceArray[indexPath.section];
view.backgroundColor = [UIColor whiteColor];
if ([wikiModel.kind isEqualToString:@"group"]) {
view.kindLabel.text = @"食物類別";
}else if ([wikiModel.kind isEqualToString:@"brand"]) {
view.kindLabel.text = @"熱門品牌";
}else if ([wikiModel.kind isEqualToString:@"restaurant"]) {
view.kindLabel.text = @"連鎖餐飲";
}else{
view.kindLabel.text = @"其他類別";
}
return view;
}else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
HJCollectionReusableView *view = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"footerView" forIndexPath:indexPath];
view.backgroundColor = [UIColor colorWithRed:218/256.0 green:218/256.0 blue:218/256.0 alpha:1];
view.kindLabel.backgroundColor = [UIColor colorWithRed:218/256.0 green:218/256.0 blue:218/256.0 alpha:1];
return view;
}
return nil;
}
item的重排問題
- 添加長按手勢UILongpressGestureRecognizer
-(void)addLongPressGestureToCollectionView{
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressHandle:)];
[self.collectionView addGestureRecognizer:longPressGesture];
}
- 監(jiān)聽手勢狀態(tài)state變化
1.beginInteractiveMovementForItemAtIndexPath: //開始移動
2.updateInteractiveMovementTargetPosition: //更新坐標
3.endInteractiveMovement: //結(jié)束移動
4.cancelInteractiveMovement: //取消移動
- dataSourceArray刪除、添加數(shù)據(jù)
第三步:dataSourceArray刪除,插入數(shù)據(jù)
#pragma mark - Action
/*cell的移動(從oldindex 移到 newindex)*/
-(void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath: (NSIndexPath *)destinationIndexPath{
//0.獲取移動的起點和終點
NSInteger from = sourceIndexPath.item;
NSInteger to = destinationIndexPath.item;
//1.獲取要刪除的數(shù)據(jù)
NSString *o = self.datasourceArray[from];
//2.刪除要移動的數(shù)據(jù)
[self.datasourceArray removeObjectAtIndex:from];
//3.插入指定的位置
[self.datasourceArray insertObject:o atIndex:to];
}
sectionInset內(nèi)邊距

dd.png
自定義Layout
- 邊界改變是否讓布局無效
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
return YES;
}
- 準備布局
/*
*注釋:第一步
* 1.實例化時最開始調(diào)用這個方法,
* 2.布局無效之后
* 3.查詢布局信息之前
* 4.如果子類覆蓋(重寫方法),子類應該總是調(diào)用super。invalidateLayout布局無效
* 5.在這里面一般就是寫collectionView、cell。。配置信息(itemSize,間距等)
*/
-(void)prepareLayout
{
[super prepareLayout];
//滾動方向
self.scrollDirection = UICollectionViewScrollDirectionVertical;
//設置collectionView內(nèi)邊距
CGFloat insert = (self.collectionView.frame.size.width - self.itemSize.width) / 2;
self.sectionInset = UIEdgeInsetsMake(insert, insert, insert, insert);
}
- 返回滾動后推薦的停留點(偏移量)
/*
*注釋:第二步
*
*返回滾動后推薦(proposed)停止的點(偏移量),在這里要進行處理
*/
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
//計算最終顯示的邊界
CGRect rect;
rect.origin.x = proposedContentOffset.x;
rect.origin.y = 0;
rect.size = self.collectionView.frame.size;
// 獲得所有顯示區(qū)域內(nèi)的布局對象
NSArray *arr = [super layoutAttributesForElementsInRect:rect];
// collectionView中心點的x值 、 偏移量 + 一半寬度 = 當前collectionView的中點對應著contentView的哪一個中點
CGFloat contentCenterX = self.collectionView.frame.size.width / 2 + proposedContentOffset.x;
//存放布局對象數(shù)組中離(上面計算的)的點最小間距的布局對象的距離
CGFloat minDistance = MAXFLOAT;
for (UICollectionViewLayoutAttributes * attr in arr) {
CGFloat distance = ABS(attr.center.x - contentCenterX);
minDistance = minDistance > distance ? distance : minDistance;
}
//處理推薦的點,達到每次都停在圖片中間的效果(之所以明確是?,因為偏移一定是負數(shù))
proposedContentOffset.x += minDistance;
return proposedContentOffset;
}
- 重新布局可視范圍視圖內(nèi)的所有子控件
/*
*注釋:第三步:重新布局所有子控件cell
*
*作用相當于layoutSubViews,最后才執(zhí)行的
*/
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
//先布局super,只有流體布局才能使用
NSArray *arr = [super layoutAttributesForElementsInRect:rect];
//計算contentView中心點
CGFloat contentCenterX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width / 2;
for (UICollectionViewLayoutAttributes *attr in arr) {
//求contentView的中心點和cell的中心點的距離[ABS:取絕對值]
CGFloat distance = ABS(attr.center.x - contentCenterX);//比不理解。。。。。。。。。。。。。。
//根據(jù)間距,計算縮放比例,
CGFloat scale = 1 - distance / self.collectionView.frame.size.width;
//設置cell的顯示比例(當cell正好處于collectionView中點)
attr.transform = CGAffineTransformMakeScale(scale, scale);
}
return arr;
}
第三方CHTCollectionViewWaterfallLayout的使用
- 組頭、組尾
- 必須實現(xiàn)的代理方法,確定itemSize
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
UICollectionReusableView *reusableView = nil;
if ([kind isEqualToString:CHTCollectionElementKindSectionHeader]) {
reusableView = [collectionView dequeueReusableSupplementaryViewOfKind:kind
withReuseIdentifier:HEADER_IDENTIFIER
forIndexPath:indexPath];
} else if ([kind isEqualToString:CHTCollectionElementKindSectionFooter]) {
reusableView = [collectionView dequeueReusableSupplementaryViewOfKind:kind
withReuseIdentifier:FOOTER_IDENTIFIER
forIndexPath:indexPath];
}
return reusableView;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return [self.cellSizes[indexPath.item] CGSizeValue];
}