商城筛选的功能的Demo,实现如下功能:【CollectionView】初步展示数据,Section展开/折叠,以及用户选择。
先展示几张Demo界面图
分析实现步骤
1.数据
手动创建一个FiltrateItem.plist,如下图展示数据模型结构
2.懒加载初始化CollectionView,字典转模型,设置数据源
- (UICollectionView *)collectionView
{
if (!_collectionView) {
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
layout.minimumLineSpacing = 10; //竖间距
layout.itemSize = CGSizeMake((FiltrateViewScreenW - 6 * 5) / 3, 30);
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionView.delegate = self;
_collectionView.dataSource = self;
_collectionView.alwaysBounceVertical = YES;
_collectionView.frame = CGRectMake(5, 0, FiltrateViewScreenW - DCMargin, ScreenH - 50);
_collectionView.showsVerticalScrollIndicator = NO;
[_collectionView registerClass:[DCAttributeItemCell class] forCellWithReuseIdentifier:DCAttributeItemCellID];//cell
[_collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([DCHeaderReusableView class]) bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:DCHeaderReusableViewID]; //头部
[_collectionView registerClass:[DCFooterReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:DCFooterReusableViewID]; //尾部
}
return _collectionView;
}
#pragma mark - 筛选Item数据
- (void)setUpFiltrateData
{
_filtrateItem = [DCFiltrateItem mj_objectArrayWithFilename:@"FiltrateItem.plist"];
}
#pragma mark - <UICollectionViewDelegate>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
//这里默认第一组品牌展示两行数据其余展示一行数据(3个一行)
return (_filtrateItem[section].isOpen == YES) ? self.filtrateItem[section].content.count : (section == 0) ? 6 : 3 ;
}
Demo中筛选控制的宽度我定义宏为窗口的宽度*0.8 ,每个Item的宽度为(FiltrateViewScreenW - 6 * 5) / 3,已经手动算上间距 如下图
#define FiltrateViewScreenW ScreenW * 0.8 //筛选宽宏
layout.itemSize = CGSizeMake((FiltrateViewScreenW - 6 * 5) / 3, 30); //算横间距
layout.minimumLineSpacing = 10; //竖间距
判断是否展开或关闭,判断Item是否点击,模型中加入两个BooL值
/** 用于判断当前cell是否展开 */
@property (nonatomic, assign) BOOL isOpen;
/** 是否点击 */
@property (nonatomic,assign)BOOL isSelect;
在DCAttributeItemCell中创建一个按钮,按钮contentButton尺寸为DCAttributeItemCell的尺寸,根据模型数据的isSelect数据,改变字体,背景颜色等设置,注意一定记得要把按钮的enabled设置为NO,不然点击事件就在按钮上不在DCAttributeItemCell上,didSelectItemAtIndexPath方法也就失效了
#pragma mark - Setter Getter Methods
- (void)setContentItem:(DCContentItem *)contentItem
{
_contentItem = contentItem;
[_contentButton setTitle:contentItem.content forState:0];
if (contentItem.isSelect) { //已选
[_contentButton setImage:[UIImage imageNamed:@"isSelectYes"] forState:0];//钩图片
[_contentButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
_contentButton.backgroundColor = [UIColor whiteColor];
[DCSpeedy dc_chageControlCircularWith:self AndSetCornerRadius:3 SetBorderWidth:1 SetBorderColor:[UIColor redColor] canMasksToBounds:YES];
}else{
[_contentButton setImage:nil forState:0];
[_contentButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_contentButton.backgroundColor = [UIColor colorWithRed:230/255.0 green:230/255.0 blue:230/255.0 alpha:1.0];
[DCSpeedy dc_chageControlCircularWith:self AndSetCornerRadius:3 SetBorderWidth:1 SetBorderColor:[UIColor clearColor] canMasksToBounds:YES];
}
}
3.根据模型获取每组选择的数据和最后总获得数据
点击事件,通过模型讲已选的属性加入数组中,这个主意我初始化的数组内部还嵌套了多个数组层次结构类似:@[@[],@[],@[]],这样我们根据内部数组的值来给每个Header赋值
#pragma mark - <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
_filtrateItem[indexPath.section].content[indexPath.row].isSelect = !_filtrateItem[indexPath.section].content[indexPath.row].isSelect;
//数组mutableCopy初始化,for循环加数组 结构大致:@[@[],@[]] 如此
_seleArray = [@[] mutableCopy];
for (NSInteger i = 0; i < _filtrateItem.count; i++) {
NSMutableArray *section = [@[] mutableCopy];
[_seleArray addObject:section];
}
//把所选的每组Item分别加入每组的数组中
for (NSInteger i = 0; i < _filtrateItem.count; i++) {
for (NSInteger j = 0; j < _filtrateItem[i].content.count; j++) {
if (_filtrateItem[i].content[j].isSelect == YES) {
[_seleArray[i] addObject:_filtrateItem[i].content[j].content];
}else{
[_seleArray[i] removeObject:_filtrateItem[i].content[j].content];
}
}
}
[collectionView reloadData];
}
header头部折叠展开点击Block回调和赋值已选属性
__weak typeof(self)weakSelf = self;
headerView.sectionClick = ^{
weakSelf.filtrateItem[indexPath.section].isOpen = !weakSelf.filtrateItem[indexPath.section].isOpen; //打开取反
[collectionView reloadData]; //刷新
};
//给每组的header的已选label赋值~
NSArray *array = _seleArray[indexPath.section];
NSString *selectName = @"";
for (NSInteger i = 0; i < array.count; i ++ ) {
if (i == array.count - 1) {
selectName = [selectName stringByAppendingString:[NSString stringWithFormat:@"%@",array[i]]];
}else{
selectName = [selectName stringByAppendingString:[NSString stringWithFormat:@"%@,",array[i]]];
}
}
headerView.selectHeadLabel.text = (selectName.length == 0) ? @"全部" : selectName;
headerView.selectHeadLabel.textColor = ([headerView.selectHeadLabel.text isEqualToString:@"全部"]) ? [UIColor darkGrayColor] : [UIColor redColor];
4.底部重置,确定点击事件处理
#pragma mark - 点击事件
- (void)bottomButtonClick:(UIButton *)button
{
if (button.tag == 0) {//重置点击
for (NSInteger i = 0; i < _filtrateItem.count; i++) {
for (NSInteger j = 0; j < _filtrateItem[i].content.count; j++) {
_filtrateItem[i].content[j].isSelect = NO;
[_seleArray[i] removeAllObjects];
}
}
[self.collectionView reloadData];
}else if (button.tag == 1){//确定点击
for (NSInteger i = 0; i < _seleArray.count; i++) {
NSArray *array = _seleArray[i];
NSString *selectName = @"";
for (NSInteger i = 0; i < array.count; i ++ ) {
if (i == array.count - 1) {
selectName = [selectName stringByAppendingString:[NSString stringWithFormat:@"%@",array[i]]];
}else{
selectName = [selectName stringByAppendingString:[NSString stringWithFormat:@"%@,",array[i]]];
}
}
if (selectName.length != 0) {
NSLog(@"已选:第%zd组 的 %@",i,selectName);
}
}
}
}