淘宝的搜索出来的商品列表可以切换样式,下面是在一个pdf的demo里面模仿了淘宝的这个功能,点一下左上角的change style
,界面由三列
变成单列
,你可以使用一个tableView
+collectionView
实现,当然,这是比较费力的办法,我们这次,只用collectionView
来实现这个效果,姿势用的好,没有xxx推不倒
众所周知,collectionView
可以自定义布局来实现圆形布局,瀑布流布局,对于这个效果,我们直接使用官方提供的uicollectionviewflowlayout
,uicollectionviewflowlayout
如同其名,在每一行,一个接一个排列,当所剩的位置不足以容下一个新的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
,修改样式如下:
选中collectionView
,在右边的属性栏将items
改为2
:
这时,collectionView
中多了一个cell
,我们将另一个的样式修改,最终在SB中的效果如下:
nice,我们已经完成了ui的部份,接下来,我们需要新建OneColumCell
和MulColumCell
对应我们在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
实现UICollectionViewDelegateFlowLayout
和UICollectionViewDataSource
协议
- (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~
看起来效果不错,等等,等等,我们刚才的kColumn
明明是3
,这里为什么还是两列
static const NSInteger kColumn = 3;
我们再仔细观察一下,我们发现cell
与cell
之间有个大概10个点
的白色间距,这里我们将cell
的背景色设置为黄色可以更好的看出这些间距,既然上下之间有了间距,所以有没有可能左右也有呢,因为我们的屏幕刚好要放下三个cell
,没有预留边距的位置,所以如果多处了间距的话,就会导致这情况,我们查看SB的属性
我们将图所圈的全部改为0,再次run~
去掉了默认的边距之后,已经达到了我们想要的效果,本文的Demo点此下载