淘宝商品列表页样式切换(CollectionView)

淘宝的搜索出来的商品列表可以切换样式,下面是在一个pdfdemo里面模仿了淘宝的这个功能,点一下左上角的change style,界面由三列变成单列,你可以使用一个tableView+collectionView实现,当然,这是比较费力的办法,我们这次,只用collectionView来实现这个效果,姿势用的好,没有xxx推不倒

enter image description here

众所周知,collectionView可以自定义布局来实现圆形布局瀑布流布局,对于这个效果,我们直接使用官方提供的uicollectionviewflowlayoutuicollectionviewflowlayout如同其名,在每一行,一个接一个排列,当所剩的位置不足以容下一个新的cell的时候,另起一行,所以,对于一列的情况,我们可以将cell的宽度设置为等于collectionView的宽度,这样每行只有一个cell,效果就和tableView一样;对于多列的情况,只要控制好cell的宽度,也可以轻松实现,关键在cell的size控制,cell的size又由layout的size所决定,所以核心操作都在

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath  

Just do it

新建一个项目,在SB里面放入一个collectionView,再拖入一个collectionViewCell,修改样式如下:

enter image description here

选中collectionView,在右边的属性栏将items改为2:

enter image description here

这时,collectionView中多了一个cell,我们将另一个的样式修改,最终在SB中的效果如下:

enter image description here

nice,我们已经完成了ui的部份,接下来,我们需要新建OneColumCellMulColumCell对应我们在SB中的两个cell,这里只贴出.m的代码:

OneColumCell.m

#import "OneColumCell.h"
#import "ProductInfoModel.h"

@interface OneColumCell()

@property (weak, nonatomic) IBOutlet UIImageView *mImageView;

@property (weak, nonatomic) IBOutlet UILabel *mTitleLabel;

@property (weak, nonatomic) IBOutlet UILabel *mDescLabel;

@property (nonatomic, strong) ProductInfoModel     *model;

@end

@implementation OneColumCell

- (void)setProductInfoModel:(ProductInfoModel *)model{
    _model = model;

    _mTitleLabel.text = model.title;

    _mDescLabel.text  = model.desc;

    if (model.image) {
        _mImageView.image = model.image;
    }
}

@end

MulColumCell.m

#import "MulColumCell.h"
#import "ProductInfoModel.h"

@interface MulColumCell()

@property (weak, nonatomic) IBOutlet UIImageView *mImageView;

@property (weak, nonatomic) IBOutlet UILabel *mTitleLabel;

@property (nonatomic, strong) ProductInfoModel     *model;

@end

@implementation MulColumCell

- (void)setProductInfoModel:(ProductInfoModel *)model{
    _model = model;

    _mTitleLabel.text = model.title;

    if (model.image) {
        _mImageView.image = model.image;
    }
}

@end

好了,是时候回到我们的ViewController中,将一切关联起来,揭开神秘的面纱

我们需要一个状态来区分当前是单列或者多列

@property (nonatomic, assign) BOOL     isSingleLine;

ViewController实现UICollectionViewDelegateFlowLayoutUICollectionViewDataSource协议

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    ProductInfoModel *model = self.dataArray[indexPath.row];
    if (self.isSingleLine)//1
    {
        OneColumCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([OneColumCell class]) forIndexPath:indexPath];
        [cell setProductInfoModel:model];
        return cell;
    }
    else
    {
        MulColumCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([MulColumCell class]) forIndexPath:indexPath];
        [cell setProductInfoModel:model];
        return cell;
    }
}  

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
        if (self.isSingleLine) {
            return CGSizeMake([self screenSize].width, 139);//2
        }
        return CGSizeMake([self screenSize].width / kColumn , 143);//3
    }

1.根据self.isSingleLine,返回不同的cell
2.此处是单列模式,将width设置为当前屏幕的宽度
3.此处是多列模式,根据定义的列数kColumn,计算出对应的宽度,在这里,我们的高度写成一个固定值是偷懒了,实际开发中应该是根据不同的屏幕去生成不同的高度,以便更好的适配

风风火火写了这么多,是时候让新娘子出来见见人了,run~

enter image description here

看起来效果不错,等等,等等,我们刚才的kColumn明明是3,这里为什么还是两列

static const NSInteger kColumn = 3;

我们再仔细观察一下,我们发现cellcell之间有个大概10个点的白色间距,这里我们将cell 的背景色设置为黄色可以更好的看出这些间距,既然上下之间有了间距,所以有没有可能左右也有呢,因为我们的屏幕刚好要放下三个cell ,没有预留边距的位置,所以如果多处了间距的话,就会导致这情况,我们查看SB的属性

enter image description here

我们将图所圈的全部改为0,再次run~

enter image description here

去掉了默认的边距之后,已经达到了我们想要的效果,本文的Demo点此下载