实现效果
设计思路
使用MJRefresh框架实现上拉和下拉刷新
使用SDWebImage框架加载图片
商品模型需要包含以下属性
/**商品控件宽度*/@PRoperty (nonatomic, assign) CGFloat w;/**商品控件高度*/@property (nonatomic, assign) CGFloat h;/**商品图片*/@property (nonatomic, copy) NSString *img;/**商品价格*/@property (nonatomic, copy) NSString *price;
通过xib来实现自定义cell(继承自UICollectionViewCell),xib的结构如图
视图的代码实现
包含商品模型属性
/**商品模型*/@property (nonatomic, strong) LYPShop *shop;
引用xib中的控件
//展示商品图片@property (weak, nonatomic) IBOutlet UIImageView *imageView;//显示商品价格@property (weak, nonatomic) IBOutlet UILabel *priceLabel;
重写商品模型的setter,使xib中的控件显示乡音的内容
- (void)setShop:(LYPShop *)shop{ _shop = shop; //使用SDWebImage设置商品图片 [self.imageView sd_setImageWithURL:[NSURL URLWithString:shop.img] placeholderImage:[UIImage imageNamed:@"loading"]]; //设置商品价格 self.priceLabel.text = shop.price;}
创建展示商品的容器,即UICollectionView对象,并初始化
- (void)setupCollectionView{ //通过封装的自定义布局,创建布局 LYPWaterFlowLayout *layout = [[LYPWaterFlowLayout alloc] init]; //设置layout的代理 layout.delegate = self; //创建collectionView UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; self.collectionView = collectionView; //设置数据源 collectionView.dataSource = self; //将collectionView添加到控制器的view中 [self.view addSubview:collectionView];}
注册通过xib自定义的cell
/**设置cell的重用标示*/static NSString *const LYPShopID = @"shop";- (void)registerCell{ //注册cell [self.collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([LYPShopCell class]) bundle:nil] forCellWithReuseIdentifier:LYPShopID];}
设置商品模型数组
添加成员属性
/**所有的商品模型数组*/@property (nonatomic, strong) NSMutableArray *shops;
通过懒加载的方式,初始化模型数组
- (NSMutableArray *)shops{ if (_shops == nil) { _shops = [NSMutableArray array]; } return _shops;}
实现刷新功能
刷新的业务逻辑,如图
设置上拉刷新和下拉刷新控件
- (void)setupRefresh{ //下拉刷新控件 self.collectionView.header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewShops)]; //view加载完毕,开始下拉刷新 [self.collectionView.header beginRefreshing]; //上拉刷新控件 self.collectionView.footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreShops)]; //一开始隐藏footer self.collectionView.footer.hidden = YES;}
实现加载数据功能
/**下拉刷新*/- (void)loadNewShops{ //通过该函数模拟网络延迟 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //将字典转成模型 NSArray *shops = [LYPShop objectArrayWithFilename:@"1.plist"]; //清空之前所有的商品模型信息 [self.shops removeAllObjects]; //将最新的商品模型信息添加到模型数组中 [self.shops addObjectsFromArray:shops]; //刷新数据 [self.collectionView reloadData]; //结束刷新 [self.collectionView.header endRefreshing]; });}/**上拉刷新*/- (void)loadMoreShops{ //通过该函数模拟网络延迟 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //通过该函数模拟网络延迟 NSArray *shops = [LYPShop objectArrayWithFilename:@"1.plist"]; //将新加载的商品模型信息添加到模型数组中 [self.shops addObjectsFromArray:shops]; //刷新数据 [self.collectionView reloadData]; //结束刷新 [self.collectionView.footer endRefreshing]; });}
设置collectionView的数据源
设置cell的个数
- (NSInteger)collectionView:(nonnull UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ //设置上拉刷新控件的状态,无商品时不显示 self.collectionView.footer.hidden = self.shops.count == 0; //返回cell的个数 return self.shops.count;}
创建indexPath位置的cell
- (UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath{ //通过重用标示从缓存池中取,若取不到,则自动创建 LYPShopCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:LYPShopID forIndexPath:indexPath]; //给视图cell的模型赋值,使其设置cell中控件的显示内容 cell.shop = self.shops[indexPath.item]; return cell;}
实现layout的代理方法,定制布局
设置每个cell的高度
- (CGFloat)waterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout heightForItemAtIndex:(NSInteger)index itemWith:(CGFloat)itemWith{ LYPShop *shop = self.shops[index]; //通过比例计算cell的高度 return itemWith * shop.h / shop.w;}
设置列数
- (NSInteger)columnCountInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout{ return 2;}
设置行间距
- (CGFloat)rowMarginInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout{ return 20;}
设置列间距
- (CGFloat)columnMarginInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout{ return 40;}
设置内边距
- (UIEdgeInsets)edgeInsetsInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout{ return UIEdgeInsetsMake(20, 10, 10, 30);}
可以简单地通过改变返回列数的代理方法,来改变布局
- (NSInteger)columnCountInWaterFlowLayout:(LYPWaterFlowLayout *)waterFlowLayout{ //返回3列 return 3;}
效果如图
新闻热点
疑难解答