需求:
需要的Button 的個(gè)數(shù)不一定 Button上顯示的字符串的長(zhǎng)度不一定,Button上顯示的字符串和Button的個(gè)數(shù)全部從服務(wù)器下發(fā) 悍汛,當(dāng)Button的個(gè)數(shù)在屏幕上展示不下的時(shí)候要可以左右滑動(dòng) 以展示更多的Button
方案:
綜合以上因素 我選擇利用CollectionView實(shí)現(xiàn)此功能.
其中遇到幾個(gè)問題:
首先說(shuō)明: cell中有一個(gè)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;
}
問題 一 :因?yàn)檫x中cell時(shí) cell的字和邊框要變成紅色 敲茄,當(dāng)再點(diǎn)擊其他Item時(shí)此item要變?yōu)樵瓉?lái)的樣子
這個(gè)功能主要在collectionView的兩個(gè)代理方法中實(shí)現(xiàn)
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;;
具體實(shí)現(xiàn)如下:
/**
* 當(dāng)點(diǎn)擊item時(shí)會(huì)調(diào)用此方法 在此方法中把點(diǎn)擊的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;
}
/**
* 當(dāng)點(diǎn)擊其他cell時(shí)調(diào)用此方法 比如點(diǎn)擊第一個(gè)cell的時(shí)候調(diào)用上面的方法藐唠,當(dāng)點(diǎn)擊第二個(gè)的時(shí)候先調(diào)用此方法誉碴,然后再調(diào)用上面的方法
在此方法中獲取第一次點(diǎn)擊的cell 即
JWCCollectionViewCell *cell = (JWCCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
把此cell 的textLabel屬性變回原來(lái)的樣子 然后系統(tǒng)會(huì)調(diào)用上面的代理方法把點(diǎn)擊的第二個(gè)cell的textLabel屬性的字體顏色和邊框改變顏色
這樣就實(shí)現(xiàn)了 點(diǎn)擊此cell改變顏色 再點(diǎn)擊其他的cell是時(shí) 上一個(gè)點(diǎn)擊的cell恢復(fù)到原來(lái)的樣子
*
*/
- (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的個(gè)數(shù)太多的話肯定會(huì)發(fā)生復(fù)用的問題:
比如數(shù):屏幕的寬度只能顯示3個(gè)cell 但是現(xiàn)在有四個(gè)需要顯示厦幅,那么當(dāng)點(diǎn)擊第一個(gè)cell 向左滑動(dòng)時(shí)會(huì)顯示第四個(gè) 這個(gè)時(shí)候第四個(gè)item就是從復(fù)用隊(duì)列中取出一個(gè)cell 蜘澜,那么這個(gè)cell可能還保留這上一個(gè)的屬性 比如說(shuō)字體是紅色的 其寬度可能會(huì)很大施流,不適合當(dāng)前的string的寬度 ,左右滑動(dòng)的時(shí)候cell 之間的間隔也會(huì)發(fā)生錯(cuò)亂 這絕不是想要的結(jié)果 鄙信。出現(xiàn)這個(gè)原因主要是cell的復(fù)用產(chǎn)生的瞪醋。
解決方法:
在cell復(fù)用之前把cell恢復(fù)到初始化狀態(tài),那么這就要重寫 - (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這個(gè)方法是CollectionViewCell的方法
但是錯(cuò)亂問題仍然沒有解決:這主要是因?yàn)樵诙x_textLabel 時(shí)它的frame設(shè)置問題 應(yīng)該在添加一句
_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;
}
問題三:
比如說(shuō) 當(dāng)點(diǎn)擊第一個(gè)cell 后 向左滑動(dòng)讓第一個(gè)消失在界面中扮碧,當(dāng)再滑出界面時(shí)你會(huì)發(fā)現(xiàn)它的選中狀態(tài)消失了趟章,而你并沒有選中其他的cell 杏糙,這是為什么?蚓土?宏侍?因?yàn)樯弦粏栴}的解決方法導(dǎo)致了這一步。那么該怎么樣解決才能不至于解決上面的問題引出下面的問題呢蜀漆?谅河?方法如下:
1, 定義一個(gè)全局變量:
@property (nonatomic ,assign)NSInteger selectIndex;
2 這個(gè)先給它賦一個(gè)永遠(yuǎn)也不可能達(dá)到的值
self.selectIndex = MAXFLOAT; //至于為什么賦這么大下面說(shuō)
3 在
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
這個(gè)代理方法中把 indexPath.row 值賦值給 self.selectIndex如下
self.selectIndex = indexPath.row;
這就記住了所選擇的item的位置
4确丢,在 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;這個(gè)方法中可能會(huì)從復(fù)用隊(duì)列中去處cell 產(chǎn)生復(fù)用 但在復(fù)用之前會(huì)調(diào)用- (void)prepareForReuse方法 又會(huì)恢復(fù)原樣使選中狀態(tài)消失绷耍,這個(gè)時(shí)候要判斷一下,判斷這個(gè)方法中的 indexPath.row 是否等于 self.selectIndex 如果等于 使其變?yōu)檫x中的狀態(tài)鲜侥,具體代碼如下:
- (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 消失在界面中在出現(xiàn)的時(shí)候也不會(huì)改變選中狀態(tài)褂始。
為什么要把self.selectIndex = MAXFLOAT
如果不這樣賦值 假如賦的值為0 那么每次打開時(shí)第一個(gè)cell就是選中狀態(tài),但是你并沒有點(diǎn)擊第一個(gè)描函。這主要是在cell生成的代理方法中的這一句代碼引起的
if (indexPath.row == _selectIndex ) {
cell.textLabel.textColor = [UIColor redColor];
cell.textLabel.layer.borderColor = [UIColor redColor].CGColor;
}
所以把self.selectIndex 賦值為 MAXFLOAT 這樣就不會(huì)有當(dāng)一啟動(dòng)APP的時(shí)候就有cell被選中的狀態(tài)
問題四:
根據(jù)string的寬度不同來(lái)生成的cell的寬度也不同的功能是在
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
實(shí)在這個(gè)方法中返回不通的CGSize 來(lái)改變每一個(gè)cell的寬度崎苗。
在此可以計(jì)算字符串的寬度:
具體的方法如下:
#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);
}
/**
* 計(jì)算字符串的寬度的方法
*/
- (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 在這個(gè)方法中需要傳入字體的大小。
這個(gè)大小一定要和 textLabel初始化時(shí)的字體大小一樣 比如本例中在初始化的時(shí)候是13 那么在計(jì)算字符串的寬度的時(shí)候一定要是13 不然計(jì)算出的字符串的寬度比實(shí)際的要長(zhǎng) :會(huì)出現(xiàn)的問題是當(dāng)左右滑動(dòng)時(shí)會(huì)出現(xiàn)各個(gè)cell之間的間隔會(huì)出現(xiàn)改變 也許會(huì)兩個(gè)cell會(huì)出現(xiàn)重疊Rㄔⅰ胆数!
_textLabel.font = [UIFont systemFontOfSize:13];
原文地址:http://blog.csdn.net/godblessmyparents/article/details/50675263