项目需要做一个书架功能,期间选取了tableview做控件,还有很多三方的框架,但是深入使用之后发现collectionView的优势在做这样的需求时还是最合适的,一点小感悟把,就想选择控件一样,很多东西其实方向错了,再怎么努力也是徒劳的。鸡汤到此为止,入正题。
首先是建立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;
}
谨此记录,欢迎指正。[email protected]