UI基础__UICollectionView__瀑布流

本文重点记录使用collectionView做应用管理、瀑布流、图片轮播器,代码下载地址:http://download.csdn.net/download/jacob_ios/9411733

创建应用管理可以使用三种情况制作:

1.使用storyboard
2.使用xib
3.纯代码实现

编码过程中的注意点记录:

UIImageView *imgView=[[UIImageView alloc]init];
    //从父容器获取子控件
    imgView=cell.contentView.subviews[0];
    XYappData *data=self.arr[indexPath.item];
    imgView.image=[UIImage imageNamed:data.icon];
    UILabel *lab=[[UILabel alloc]init];
    lab=cell.contentView.subviews[2];
    lab.text=data.name;
    return cell;

根据具体的xib文件来设置itemSize

    //instantiateWithOwner可以读取指定的xib文件,将xib文件中所有的view返回存储到数组中,同时设置top view
    HMAppCell *cell=[[nib instantiateWithOwner:self options:nil] lastObject];
    //设置布局属性
    self.layout.itemSize=CGSizeMake(cell.frame.size.width, cell.frame.size.height);

使用xib注册cell

    //1.名称:区分大小写,不要扩展名
    //2.如果是nil,则默认就是mainBundle
    //UINib *nib=[UINib nibWithNibName:@"HMAppCell" bundle:[NSBundle mainBundle]];
    UINib *nib=[UINib nibWithNibName:@"HMAppCell" bundle:nil];
    [self.collectionView registerNib:nib forCellWithReuseIdentifier:@"app"];

//**********************881.找缓存cell
    //2.如果没有缓存cell,就去找原型cell
    HMAppCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"app" forIndexPath:indexPath];
    cell.app=self.apps[indexPath.item];
    return cell;

设置header和footer

//设置头部和底部view--只有实现这个方法才能够正常的显示头部和底部
//什么时候调用这个方法:当你当前的视图能够看到头部view或者底部view的时候就会调用这个方法来创建头部或者底部view
//并不是一开始就创建好
- (UICollectionReusableView *) collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    NSString *ID=@"header";
    if (kind==UICollectionElementKindSectionFooter) {
        ID=@"footer";
    }
    UICollectionReusableView *userView=[collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:ID
        forIndexPath:indexPath];
    //NSLog(@"%@",kind);
    return  userView;
}

瀑布流的制作

关键点:
1.设置底部视图的时候,需要点是把footer进行封装,有利于对其控制,

//设置底部视图
-(UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
    XYshopFooter *footer=nil;
    if (kind==UICollectionElementKindSectionFooter) {
    footer=[collectionView dequeueReusableSupplementaryViewOfKind: kind withReuseIdentifier:@"footer" forIndexPath:indexPath];
// NSLog(@"footer");
        //让菊花开始转动
        [footer.grayView startAnimating];
        //延迟操作,加载数据,
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            //加载
            [self loadData];

            //刷新界面
            [self.collectionView reloadData];
        });

          return footer;
            }

    return nil;
}

2.数据加载的时候,需注意:

//懒加载
-(NSMutableArray *)arr{
    if (_arr==nil) {
        _arr=[NSMutableArray array];
    }
    return _arr;
}
//
-(void)loadData{
    NSMutableArray *arrM=[XYshoping arr:self.index];
    self.index++;
    [self.arr addObjectsFromArray:arrM];

}

3.把布局属性进行封装,进行frame值的获取

注意:在生成底部视图的时候,需要在下次加载之前删除一个footer ,不然会出现两个footer
将i改为从self.attArr.count开始,可以避免在数据刷新的时候上次的数据为空
若实现全部的自动布局,将self.attArr.count清空,并在此从0开始布局,这样在换屏的时候可以从新布局,实现效果

@interface XYlayout()
//存储cell的frame值的数组
@property(nonatomic,strong)NSMutableArray *attArr;
//存储每一列的
@property(nonatomic,strong)NSMutableDictionary *mutYDic;
@end

@implementation XYlayout
-(NSMutableArray *)attArr{
    if (_attArr==nil) {
        _attArr=[NSMutableArray array];
    }
    return _attArr;
}
//初始化Y值,从顶部的位置开始
-(NSMutableDictionary *)mutYDic{
    if (_mutYDic==nil) {
        _mutYDic=[NSMutableDictionary dictionary];
        for (int i=0; i<self.countLine; i++) {
            NSString *key=[NSString stringWithFormat:@"%d",i];
            _mutYDic[key]=@(self.sectionInset.top);
        }
    }
    return _mutYDic;
}
//每次布局的时候调用该方法
-(void)prepareLayout{
    NSLog(@"preparelayout");
    //删除底部的值,不然会出现两个footer
    [self.attArr removeLastObject];
    NSInteger total=[self.collectionView numberOfItemsInSection:0];
    //将i改为从self.attArr.count开始,可以避免在数据刷新的时候上次的数据为空
    //若实现全部的自动布局,将self.attArr.count清空,并在此从0开始布局
    self.mutYDic=nil;
    for (NSInteger i=0; i<total; i++) {
        //确定某个位置上
        NSIndexPath *path=[NSIndexPath indexPathForItem:i inSection:0];
        UICollectionViewLayoutAttributes *att=[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];

        //计算宽
        CGFloat width=(self.collectionView.bounds.size.width-self.sectionInset.left-self.sectionInset.right-self.minimumInteritemSpacing*(self.countLine-1))/(self.countLine);
        //计算高,代理实现
// XYshoping *shop=self.shop[i];
// CGFloat height=(width*shop.height)/shop.width;
        CGFloat height= [self.delegate heightForIndex:i withWidth:width];
        //计算X
// CGFloat x=self.sectionInset.left+(width+self.minimumInteritemSpacing)*(i%self.countLine);
        NSString *minCol=[self minCol];
        CGFloat x=self.sectionInset.left+(width+self.minimumInteritemSpacing)*[minCol floatValue];
        //计算Y
// NSString *col=[NSString stringWithFormat:@"%ld",i%self.countLine];
        CGFloat y=[self.mutYDic[minCol] floatValue];
        att.frame=CGRectMake(x, y, width, height);
        //重置y
// y=[@(y+height+self.minimumLineSpacing) floatValue];
        self.mutYDic[minCol]=@(y+height+self.minimumLineSpacing);
        //将att加入到数组中
        [self.attArr addObject:att];
    }
    //设置底部frame值
    NSIndexPath *path=[NSIndexPath indexPathForItem:0 inSection:0];
    UICollectionViewLayoutAttributes *footer=[UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:path];
    NSString *maxCol=[self maxCol];
    footer.frame=CGRectMake(0, [self.mutYDic[maxCol] floatValue], self.collectionView.bounds.size.width, self.footerReferenceSize.height);
    [self.attArr addObject:footer];

}
//确定滚动的范围
-(CGSize)collectionViewContentSize{
     NSString *maxCol=[self maxCol];
    CGSize size=CGSizeMake(self.collectionView.bounds.size.width, [self.mutYDic[maxCol] floatValue]+self.footerReferenceSize.height);
    return size;
}
//比较最大的Y值
-(NSString*)maxCol{
    NSString *maxCol=@"0";
    for (int i=0; i<self.countLine; i++) {
        NSString *col=[NSString stringWithFormat:@"%d",i];
        if ([self.mutYDic[col] floatValue]>[self.mutYDic[maxCol] floatValue]) {
            maxCol=col;
        }
    }

    return maxCol;
}
//比较最大的Y值
-(NSString*)minCol{
    NSString *minCol=@"0";
    for (int i=0; i<self.countLine; i++) {
        NSString *col=[NSString stringWithFormat:@"%d",i];
        if ([self.mutYDic[col] floatValue]<[self.mutYDic[minCol] floatValue]) {
            minCol=col;
        }
    }

    return minCol;
}
//系统会调用这个方法,接收布局属性数组,用于每一个cell的布局
//系统的布局数组我们并不需要,我们需要自己重新计算每一个cell的布局属性,。返回给collectionView使用
//返回数组
-(NSArray<UICollectionViewLayoutAttributes*>*)layoutAttributesForElementsInRect:(CGRect)rect{
    [super layoutAttributesForElementsInRect:rect];
    return self.attArr;
}
@end

图片轮播器

重点是坐标的计算

//确定cell
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    XYImgCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"img" forIndexPath:indexPath];
    //在拖拽的时候改变
    NSInteger index=(indexPath.item-1+ctn+self.currentIndex)%ctn;
// NSInteger index=(self.currentIndex-1)%ctn;
// NSLog(@"cell-%ld",index);
    cell.img=self.arrImg[index];
    cell.indexPath=indexPath;
    return cell;

}
//每次拖拽的时候都回到索引为1的地方,但是改变显示的图片
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

    //获得偏移量
    NSInteger offset=self.collectionView.contentOffset.x/self.collectionView.bounds.size.width-1;
    self.currentIndex=(offset+ctn+self.currentIndex)%ctn;
// NSLog(@"滚动-%ld",self.currentIndex);
   //实现单线程操作,避免快速拖拽的时候出现混乱
    dispatch_async(dispatch_get_main_queue(), ^{
         //让第一次显示的索引在为1的位置,但显示第0张图片
        NSIndexPath *path=[NSIndexPath indexPathForItem:1 inSection:0];
        [self.collectionView scrollToItemAtIndexPath:path atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
    });

    }

你可能感兴趣的:(UI,Collection)