纯代码写CollectionViewCell的复用问题
2016-08-13 17:40
381 查看
需求:
需要的Button 的个数不一定 Button上显示的字符串的长度不一定,Button上显示的字符串和Button的个数全部从服务器下发 ,当Button的个数在屏幕上展示不下的时候要可以左右滑动 以展示更多的Button
方案:
综合以上因素 我选择利用CollectionView实现此功能.
其中遇到几个问题:
首先说明:
cell中有一个Label 属性
- (UILabel *)textLabel{
if (!_textLabel)
{
_textLabel =
[[UILabelalloc]initWithFrame:self.contentView.frame];
_textLabel.layer.borderWidth = 1;
_textLabel.layer.borderColor =
[UIColorlightGrayColor].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 =
[UIColorredColor].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 =
[UIColorlightGrayColor].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 =
[UIColorlightGrayColor].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 =
[[UILabelalloc]initWithFrame:self.contentView.frame];
_textLabel.layer.borderWidth = 1;
_textLabel.layer.borderColor =
[UIColorlightGrayColor].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
= [collectionViewdequeueReusableCellWithReuseIdentifier:@"cellID"forIndexPath:indexPath
];
if (indexPath.row == _selectIndex )
{
cell.textLabel.textColor =
[UIColor redColor];
cell.textLabel.layer.borderColor =
[UIColorredColor].CGColor;
}
cell.textLabel.text =
[self.dataSourceArrobjectAtIndex: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 =
[UIColorredColor].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.dataSourceArrobjectAtIndex: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
= [aStringboundingRectWithSize: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];
需要的Button 的个数不一定 Button上显示的字符串的长度不一定,Button上显示的字符串和Button的个数全部从服务器下发 ,当Button的个数在屏幕上展示不下的时候要可以左右滑动 以展示更多的Button
方案:
综合以上因素 我选择利用CollectionView实现此功能.
其中遇到几个问题:
首先说明:
cell中有一个Label 属性
- (UILabel *)textLabel{
if (!_textLabel)
{
_textLabel =
[[UILabelalloc]initWithFrame:self.contentView.frame];
_textLabel.layer.borderWidth = 1;
_textLabel.layer.borderColor =
[UIColorlightGrayColor].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 =
[UIColorredColor].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 =
[UIColorlightGrayColor].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 =
[UIColorlightGrayColor].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 =
[[UILabelalloc]initWithFrame:self.contentView.frame];
_textLabel.layer.borderWidth = 1;
_textLabel.layer.borderColor =
[UIColorlightGrayColor].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
= [collectionViewdequeueReusableCellWithReuseIdentifier:@"cellID"forIndexPath:indexPath
];
if (indexPath.row == _selectIndex )
{
cell.textLabel.textColor =
[UIColor redColor];
cell.textLabel.layer.borderColor =
[UIColorredColor].CGColor;
}
cell.textLabel.text =
[self.dataSourceArrobjectAtIndex: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 =
[UIColorredColor].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.dataSourceArrobjectAtIndex: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
= [aStringboundingRectWithSize: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];
相关文章推荐
- 纯代码写CollectionViewCell的复用问题
- iOS 使用tableview 代码布局时,tableViewCell宽度问题,运行在iPhone 6plus 仍然显示320
- Collectionview学习(三)不使用故事版,纯代码编写cell(cell也可从nib文件加载)
- Swift3.0 自定义tableView复用cell 的写法,与CollectionViewCell的不同,数据model
- tableView中cell的删除、插入、移动、复制粘贴问题详解代码分析
- collectionViewCell防止复用的两种方法
- ios collectionView中cell不居中往上偏移问题
- 一 swift之UICollectionView纯代码cell的复用、footerView的添加
- tableView的cell的复用问题
- collectionviewcell 添加删除按钮 响应区域的问题
- 关于UITableView的cell复用问题的3种解决方法
- collectionView 防止cell复用的方法
- tableview 点击cell改变cell中的label.text的字体颜色,cell复用出现问题的解决方案2
- 关于tableView的cell复用问题
- 这里总结一下collection cell的三种创建方式的相关步骤,原形cell,xib,代码;还有对collection view的数据流flowlayout属性与collectionview的头底
- iOS中collectionViewCell显示不正确的问题
- 解决tableView cell添加阴影滑动卡顿问题,只需多两行代码
- 解决RecyclerView代码复用问题
- tableview 自定义cell 点击cell改变cell中的label.text的字体颜色,cell复用出现问题
- IOS collectionViewCell防止复用的两种方法