解决collectionview复用机制带来的麻烦(非原创)

需求:

需要的Button 的个数不一定 Button上显示的字符串的长度不一定,Button上显示的字符串和Button的个数全部从服务器下发 ,当Button的个数在屏幕上展示不下的时候要可以左右滑动 以展示更多的Button

方案:

综合以上因素 我选择利用CollectionView实现此功能.

其中遇到几个问题:

首先说明: cell中有一个Label 属性

- (UILabel *)textLabel{

if (!_textLabel) {

_textLabel = [[UILabel alloc]initWithFrame:self.contentView.frame];

_textLabel.layer.borderWidth = 1;

_textLabel.layer.borderColor = [UIColor lightGrayColor].CGColor;

_textLabel.font = [UIFont systemFontOfSize:13];

_textLabel.textAlignment = NSTextAlignmentCenter;

_textLabel.textColor = [UIColor blackColor];

[self.contentView addSubview:_textLabel];

}

_textLabel.frame = CGRectMake(CGRectGetMinX(self.contentView.frame), CGRectGetMinY(self.contentView.frame), self.frame.size.width, self.frame.size.height);

return _textLabel;

}

问题 一 :因为选中cell时 cell的字和边框要变成红色 ,当再点击其他Item时此item要变为原来的样子

这个功能主要在collectionView的两个代理方法中实现

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;;

具体实现如下:

/**

*  当点击item时会调用此方法 在此方法中把点击的item的textLabel属性的字体颜色和边框改变颜色

*

*/

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{

JWCCollectionViewCell *cell = (JWCCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];

cell.textLabel.textColor = [UIColor redColor];

cell.textLabel.layer.borderColor = [UIColor redColor].CGColor;

}

/**

*  当点击其他cell时调用此方法 比如点击第一个cell的时候调用上面的方法,当点击第二个的时候先调用此方法,然后再调用上面的方法

在此方法中获取第一次点击的cell 即

JWCCollectionViewCell *cell = (JWCCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];

把此cell 的textLabel属性变回原来的样子 然后系统会调用上面的代理方法把点击的第二个cell的textLabel属性的字体颜色和边框改变颜色

这样就实现了 点击此cell改变颜色 再点击其他的cell是时 上一个点击的cell恢复到原来的样子

*

*/

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{

JWCCollectionViewCell *cell = (JWCCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];

cell.textLabel.textColor = [UIColor blackColor];

cell.textLabel.layer.borderColor = [UIColor lightGrayColor].CGColor;

}

问题二:

假如cell的个数太多的话肯定会发生复用的问题:

比如数:屏幕的宽度只能显示3个cell 但是现在有四个需要显示,那么当点击第一个cell 向左滑动时会显示第四个 这个时候第四个item就是从复用队列中取出一个cell ,那么这个cell可能还保留这上一个的属性 比如说字体是红色的 其宽度可能会很大,不适合当前的string的宽度 ,左右滑动的时候cell 之间的间隔也会发生错乱 这绝不是想要的结果 。出现这个原因主要是cell的复用产生的。

解决方法:

在cell复用之前把cell恢复到初始化状态,那么这就要重写 - (void)prepareForReuse方法

具体做法如下:

- (void)prepareForReuse{

[super prepareForReuse];

_textLabel.frame = self.contentView.frame;

_textLabel.layer.borderWidth = 1;

_textLabel.textColor = [UIColor blackColor];

_textLabel.layer.borderColor = [UIColor lightGrayColor].CGColor;

}

这样就解决了颜色问题

注意:prepareForReuse这个方法是CollectionViewCell的方法

但是错乱问题仍然没有解决:这主要是因为在定义_textLabel 时它的frame设置问题 应该在添加一句

_textLabel.frame = CGRectMake(CGRectGetMinX(self.contentView.frame), CGRectGetMinY(self.contentView.frame), self.frame.size.width, self.frame.size.height);

具体是这样的

----------------------------------------------------------------------------------------------

- (UILabel *)textLabel{

if (!_textLabel) {

_textLabel = [[UILabel alloc]initWithFrame:self.contentView.frame];

_textLabel.layer.borderWidth = 1;

_textLabel.layer.borderColor = [UIColor lightGrayColor].CGColor;

_textLabel.font = [UIFont systemFontOfSize:13];

_textLabel.textAlignment = NSTextAlignmentCenter;

_textLabel.textColor = [UIColor blackColor];

[self.contentView addSubview:_textLabel];

}

_textLabel.frame = CGRectMake(CGRectGetMinX(self.contentView.frame), CGRectGetMinY(self.contentView.frame), self.frame.size.width, self.frame.size.height);

return _textLabel;

}

----------------------------------------------------------------------------------------------

问题三:

比如说 当点击第一个cell 后 向左滑动让第一个消失在界面中,当再滑出界面时你会发现它的选中状态消失了,而你并没有选中其他的cell ,这是为什么???因为上一问题的解决方法导致了这一步。那么该怎么样解决才能不至于解决上面的问题引出下面的问题呢??方法如下:

1,  定义一个全局变量:

@property (nonatomic ,assign)NSInteger selectIndex;

2 这个先给它赋一个永远也不可能达到的值

self.selectIndex = MAXFLOAT;至于为什么赋这么大下面说

3,在 - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;这个代理方法中把 indexPath.row 值赋值给 self.selectIndex如下

self.selectIndex = indexPath.row; 这就记住了所选择的item的位置

4,在 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;这个方法中可能会从复用队列中去处cell 产生复用 但在复用之前会调用- (void)prepareForReuse方法 又会恢复原样使选中状态消失,这个时候要判断一下,判断这个方法中的 indexPath.row 是否等于 self.selectIndex 如果等于 使其变为选中的状态,具体代码如下:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

JWCCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath ];

if (indexPath.row == _selectIndex ) {

cell.textLabel.textColor = [UIColor redColor];

cell.textLabel.layer.borderColor = [UIColor redColor].CGColor;

}

cell.textLabel.text = [self.dataSourceArr objectAtIndex:indexPath.item];

NSLog(@"%@",cell.textLabel.text);

return cell;

}

这样即使选中的cell 消失在界面中在出现的时候也不会改变选中状态。

为什么要把self.selectIndex = MAXFLOAT

如果不这样赋值  假如赋的值为0 那么每次打开时第一个cell就是选中状态,但是你并没有点击第一个。这主要是在cell生成的代理方法中的这一句代码引起的

if (indexPath.row == _selectIndex ) {

cell.textLabel.textColor = [UIColor redColor];

cell.textLabel.layer.borderColor = [UIColor redColor].CGColor;

}

所以把self.selectIndex 赋值为 MAXFLOAT 这样就不会有当一启动APP的时候就有cell被选中的状态

问题四:

根据string的宽度不同来生成的cell的宽度也不同的功能是在

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

实在这个方法中返回不通的CGSize 来改变每一个cell的宽度。

在此可以计算字符串的宽度:

具体的方法如下:

#pragma mark - UICollectionViewFlowLayoutDelegate

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{

NSString *str =  [self.dataSourceArr objectAtIndex:indexPath.item];

CGRect rect = [self getStringRect:str withFont:13];

return CGSizeMake(rect.size.width, 30);

}

/**

*  计算字符串的宽度的方法

*/

- (CGRect)getStringRect:(NSString*)aString withFont :(CGFloat)font

{

CGRect rect;

if(aString){

CGRect rect = [aString boundingRectWithSize:CGSizeMake(MAXFLOAT, 30) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:font]} context:nil];

return  rect;

}

return rect;

}

注意注意:!!!!

- (CGRect)getStringRect:(NSString*)aString withFont :(CGFloat)font 在这个方法中需要传入字体的大小。

这个大小一定要和 textLabel初始化时的字体大小一样 比如本例中在初始化的时候是13 那么在计算字符串的宽度的时候一定要是13 不然计算出的字符串的宽度比实际的要长 :会出现的问题是当左右滑动时会出现各个cell之间的间隔会出现改变 也许会两个cell会出现重叠!!

_textLabel.font = [UIFont systemFontOfSize:13];


原文地址:http://blog.csdn.net/godblessmyparents/article/details/50675263

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容