关于CollectionView的九宫格排布,多选,全选实现及删除
2015-11-20 14:45
375 查看
项目需要做一个书架功能,期间选取了tableview做控件,还有很多三方的框架,但是深入使用之后发现collectionView的优势在做这样的需求时还是最合适的,一点小感悟把,就想选择控件一样,很多东西其实方向错了,再怎么努力也是徒劳的。鸡汤到此为止,入正题。
首先是建立collectionView和一些他的必要代理,代码如下。
其中cellForItems这个代理中的ShelfLabel是自己定义的一个继承与UICollectionViewCell的类,因为CollectionViewCell没有默认的,所以需要自定义。因为需要正常状态点击跳转书籍阅读页面,长按出现书架编辑页面,所以需要加一个长按手势在这个代理中。
而区分这两个点击事件需要一个全局变量来判断,笔者在做这个功能时想了很多奇葩的弯路,诸如长按手势之后再给每一个item加单选手势,施行下去发现难度极大。过程很痛苦就不赘述了,最终选择的方案是定义一个Bool类型的全局变量ClikMode,分为未长按和长按后两种状态,效果也达到了预期
谨此记录,欢迎指正。541370008@qq.com
首先是建立collectionView和一些他的必要代理,代码如下。
其中cellForItems这个代理中的ShelfLabel是自己定义的一个继承与UICollectionViewCell的类,因为CollectionViewCell没有默认的,所以需要自定义。因为需要正常状态点击跳转书籍阅读页面,长按出现书架编辑页面,所以需要加一个长按手势在这个代理中。
/******************************************CollectionView的创建和代理**************************/ /******************************************CollectionView的创建和代理**************************/ /******************************************CollectionView的创建和代理**************************/ - (void)CreatColletionViewAsShelf { UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init]; CollectVShelf = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, UIScreenWidth, UIScreenHeight-108) collectionViewLayout:flowLayout]; [CollectVShelf registerNib:[UINib nibWithNibName:@"HomeShelfCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:STRIDENT]; CollectVShelf.backgroundColor = [UIColor colorWithRed:241/255.0 green:241/255.0 blue:241/255.0 alpha:1]; [self.view addSubview:CollectVShelf]; CollectVShelf.delegate = self; CollectVShelf.dataSource = self; } //共有多少个单元格 - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return arrIMG.count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { HomeShelfCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:STRIDENT forIndexPath:indexPath]; [cell.ShelfimgView setImageWithURL:[NSURL URLWithString:arrIMG[indexPath.row]] placeholderImage:[UIImage imageNamed:@""]]; cell.Shelflabel.text = arrBookName[indexPath.row]; cell.ShelfimgView.userInteractionEnabled = YES; cell.m_checkImageView.image = [UIImage imageNamed:@""]; cell.tag = indexPath.row; UILongPressGestureRecognizer *tap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(tapGes:)]; [cell addGestureRecognizer:tap]; return cell; }
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return CGSizeMake(100, 170); } //边距 - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { return UIEdgeInsetsMake(20, 20, 0, 20); }
而区分这两个点击事件需要一个全局变量来判断,笔者在做这个功能时想了很多奇葩的弯路,诸如长按手势之后再给每一个item加单选手势,施行下去发现难度极大。过程很痛苦就不赘述了,最终选择的方案是定义一个Bool类型的全局变量ClikMode,分为未长按和长按后两种状态,效果也达到了预期
//点击选中 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if (CLickMode == YES) { UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath]; NSLog(@"%ld",(long)indexPath.row); readViewController *readV = [[readViewController alloc] init]; readV.bookID = arrBookID[indexPath.row];; readV.bookNameStr = @"ef"; readV.bookUrlStr = @"sdf"; readV.strChapOrder = @"1"; readV.bookContent = @[]; readV.bookNewSection = @""; readV.bookAuthor = @""; [self presentViewController:readV animated:YES completion:nil]; } if (CLickMode == NO) { [CollectVShelf deselectItemAtIndexPath:indexPath animated:YES]; HomeShelfCollectionViewCell *cell = (HomeShelfCollectionViewCell*)[collectionView cellForItemAtIndexPath:indexPath]; NSMutableDictionary *dic = [contacts objectAtIndex:indexPath.row]; if ([[dic objectForKey:@"checked"] isEqualToString:@"NO"]) { [dic setObject:@"YES" forKey:@"checked"]; [cell setChecked:YES]; NSString *str = [NSString stringWithFormat:@"%ld",(long)indexPath.row]; NSLog(@"%@",arrBookID[indexPath.row]); if (mutaArrForDelete)//剔除重复的 { if ([mutaArrForDelete containsObject:str]) { return; } else [mutaArrForDelete addObject:str]; NSLog(@"%@",mutaArrForDelete); } } else { [dic setObject:@"NO" forKey:@"checked"]; [cell setChecked:NO]; NSString *str = [NSString stringWithFormat:@"%ld",(long)indexPath.row]; if (mutaArrForDelete)//剔除重复的 { if ([mutaArrForDelete containsObject:str]) { [mutaArrForDelete removeObject:str]; } else return; } } } }长按手势的事件代码如下,代码作用是首先将ClikMode状态置为NO,改变点击事件为选择某本书。然后就是navigitonItem的更改,将原来左右两边两个item改为全选和完成两个选项。并且在底部弹出一个新建的view :viewforEdit 用来显示删除和其他的一些自定义事件
-(void)tapGes:(UITapGestureRecognizer*)now { CLickMode = NO; self.navigationItem.rightBarButtonItem = nil; self.navigationItem.leftBarButtonItem = nil; NSArray *anArrayOfIndexPath = [NSArray arrayWithArray:[CollectVShelf indexPathsForVisibleItems]]; NSUInteger row = now.view.tag; NSMutableDictionary *dic = [contacts objectAtIndex:row]; //一开始将所有状态设置为未选择状态 for (int i = 0; i < [anArrayOfIndexPath count]; i++) { NSIndexPath *indexPath= [anArrayOfIndexPath objectAtIndex:i]; HomeShelfCollectionViewCell *cell = (HomeShelfCollectionViewCell*)[CollectVShelf cellForItemAtIndexPath:indexPath]; if ([[dic objectForKey:@"checked"] isEqualToString:@"NO"]) { [dic setObject:@"NO" forKey:@"checked"]; [cell setChecked:NO]; }else { [dic setObject:@"NO" forKey:@"checked"]; [cell setChecked:YES]; } } LogInButton = [[UIBarButtonItem alloc]initWithTitle:@"全选" style:UIBarButtonItemStylePlain target:self action:@selector(allSelectedBarEditClick:)]; if ([self.navigationItem respondsToSelector:@selector(leftBarButtonItems)]) { self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:LogInButton, nil]; }else { self.navigationItem.leftBarButtonItem = LogInButton; } UIBarButtonItem *menuButton = [[UIBarButtonItem alloc]initWithTitle:@"完成" style:UIBarButtonItemStylePlain target:self action:@selector(endEditingBarEditClick:)]; if ([self.navigationItem respondsToSelector:@selector(rightBarButtonItems)]) { self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:menuButton,nil]; }else { self.navigationItem.rightBarButtonItem = menuButton; } self.navigationItem.leftBarButtonItem.tintColor = [UIColor whiteColor]; self.navigationItem.rightBarButtonItem.tintColor = [UIColor whiteColor]; viewForEidit = [[UIView alloc]initWithFrame:CGRectMake(0, UIScreenHeight-152, UIScreenWidth, 44)]; viewForEidit.tag = 1001; viewForEidit.backgroundColor = [UIColor whiteColor]; [self.view addSubview:viewForEidit]; UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(40,10, (UIScreenWidth-200)/2, 24)]; [btn setTitle:@"删除" forState:UIControlStateNormal]; [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [viewForEidit addSubview:btn]; btn.tag = 701; [btn addTarget:self action:@selector(clicktoEdit:) forControlEvents: UIControlEventTouchUpInside]; UIButton *btn2 = [[UIButton alloc]initWithFrame:CGRectMake(UIScreenWidth-40-(UIScreenWidth-200)/2,10, (UIScreenWidth-200)/2, 24)]; btn2.tag = 702; [btn2 setTitle:@"其他" forState:UIControlStateNormal]; [btn2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [viewForEidit addSubview:btn2]; [btn2 addTarget:self action:@selector(clicktoEdit:) forControlEvents: UIControlEventTouchUpInside]; }全选,完成,还有删除的每个事件如下,我这里用到了数据库删除和界面删除两个删除选项,也有存Plist中这样的方式,大家可以自行在代码中查阅,因为没有代表性就不解释了。其中选择几本书同步删除这个功能需要特别注意,需要用到NSIndexSet,而不是一个简单的For语句就能搞定,因为删除了一本书之后,CollectionView会自动更新,这时你用来记录删除书的标号的数组就不正确了,所以要用到NSIndexSet。
- (void)allSelectedBarEditClick:(UIBarButtonItem *)sender { NSArray *anArrayOfIndexPath = [NSArray arrayWithArray:[CollectVShelf indexPathsForVisibleItems]]; for (int i = 0; i < [anArrayOfIndexPath count]; i++) { NSIndexPath *indexPath= [anArrayOfIndexPath objectAtIndex:i]; HomeShelfCollectionViewCell *cell = (HomeShelfCollectionViewCell*)[CollectVShelf cellForItemAtIndexPath:indexPath]; NSUInteger row = indexPath.row; NSLog(@"%lu",(unsigned long)row); NSMutableDictionary *dic = [contacts objectAtIndex:row]; if ([LogInButton.title isEqualToString:@"全选"]) { [dic setObject:@"YES" forKey:@"checked"]; [cell setChecked:YES]; }else { [dic setObject:@"NO" forKey:@"checked"]; [cell setChecked:NO]; } } if ([LogInButton.title isEqualToString:@"全选"]) { for (NSDictionary *dic in contacts) { [dic setValue:@"YES" forKey:@"checked"]; } LogInButton.title = @"取消"; } else { for (NSDictionary *dic in contacts) { [dic setValue:@"NO" forKey:@"checked"]; } LogInButton.title = @"全选"; } } - (void)endEditingBarEditClick:(UIButton *)sender { CLickMode = YES; for (UIView *view in [self.view subviews]) { if([view isKindOfClass:[UIView class]] &&1001 == view.tag)//如果有多个同类型的View可以通过tag来区分 { view.hidden = YES; [view removeFromSuperview];//删除此控件 } } self.navigationItem.rightBarButtonItem = nil; self.navigationItem.leftBarButtonItem = nil; [self navigitionBarItem]; mutaArrForDelete = [[NSMutableArray alloc]init]; [CollectVShelf reloadData];//去除编辑图片的角标 } - (void)clicktoEdit:(UIButton*)sender { if (sender.tag == 701) { NSLog(@"delete"); articleInfoViewController *articleVC = [[articleInfoViewController alloc]init]; NSMutableIndexSet *mut_set = [[NSMutableIndexSet alloc]init]; for (NSString *str in mutaArrForDelete) { NSInteger a = [str integerValue]; [mut_set addIndex:a]; } NSIndexSet *set = [[NSIndexSet alloc]initWithIndexSet:mut_set]; NSMutableArray *IDarrSelected = [[NSMutableArray alloc]init]; for (NSString*str in mutaArrForDelete) { NSInteger t = [str integerValue]; [IDarrSelected addObject:arrBookID[t]]; } [articleVC deleteSelected:IDarrSelected]; [arrBookName removeObjectsAtIndexes:set]; [arrIMG removeObjectsAtIndexes:set]; [arrBookID removeObjectsAtIndexes:set]; [downLoadBookAuthor removeObjectsAtIndexes:set]; [downLoadBookNewSection removeObjectsAtIndexes:set]; [downLoadBookContent removeObjectsAtIndexes:set]; [CollectVShelf reloadData]; //这里初始化是为了删除一次之后用户继续再删除,删除的书的序号数组初始化,防止数组崩 mutaArrForDelete = [[NSMutableArray alloc]init]; // [ deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; }else { NSLog(@"others"); } }上面用到的SetChecked这个方法是在自定义CEll的.m文件中实现的,暴露出接口以供在本类中调用,目的就是实现编辑书架时点几书改变图标的选择和未选择状态
- (void)setChecked:(BOOL)checked{ if (checked) { _m_checkImageView.image = [UIImage imageNamed:@"选中"]; self.backgroundView.backgroundColor = [UIColor colorWithRed:223.0/255.0 green:230.0/255.0 blue:250.0/255.0 alpha:1.0]; } else { _m_checkImageView.image = [UIImage imageNamed:@"未选中"]; self.backgroundView.backgroundColor = [UIColor whiteColor]; } m_checked = checked; }
谨此记录,欢迎指正。541370008@qq.com
相关文章推荐
- ksimagenamed xcode
- 【转】学习使用Jmeter做压力测试(三)--数据库测试
- Java基础02 方法与数据成员
- builder-设计模式
- 关于无限空间技术的简单猜想
- java 多线程剖析
- 更改 android realtek的系统权限
- ajax POST方式数据传递
- EBS R12.2快速安装前没有配置Global Inventory报错
- 微信开发问题
- [MethodImpl(MethodImplOptions.Synchronized)]
- npm上传自己的项目
- redis未授权访问漏洞
- 算法笔记3
- 使用node-webkit开发exe窗口程序
- linux 安装mysql
- mysql 导出数据到txt文件
- 【UVA 10307 Killing Aliens in Borg Maze】最小生成树, kruscal, bfs
- 编程:对经验世界的析构与建构
- android中RelativeLayout无法填充ScrollView布局的问题