iOS UICollection View 탭 선택 기 구현

6873 단어 iOS라벨선택 기
최근 프로젝트 에 서 는 관심 태그 와 유사 한 선택 기 가 필요 하 다.탭 의 텍스트 길이 가 정 해 지지 않 아 탭 의 표시 길이 가 정 해 지지 않 습 니 다.효 과 를 위해 UICollectionView 를 사용 하여 각 줄 의 태그 수량 이 일정 하지 않 고 cell 의 너비 가 스스로 적응 하 는 효 과 를 실현 합 니 다.먼저 여기 서 공유 하기:
1.자가 적응 UICollectionViewCell
UICollection ViewCell 에 적응 하기 위해 UICollection ViewCell 과 같은 크기 의 단 추 를 놓 습 니 다.선택 하고 취소 할 때 단추 의 텍스트 색상 과 테두리 색상 을 변경 합 니 다.

#pragma mark---  cell
@implementation YLTagsCollectionViewCell
-(instancetype)initWithFrame:(CGRect)frame
{
 if(self = [super initWithFrame:frame]){
  self.backgroundColor = [UIColor clearColor];
  _btn = [UIButton buttonWithType:UIButtonTypeCustom];
  //                    
  _btn.frame = CGRectMake(0, 0, frame.size.width, frame.size.height);
  _btn.backgroundColor = [UIColor whiteColor];
  _btn.titleLabel.font = [UIFont systemFontOfSize:14];
  _btn.layer.borderWidth = 1.f;
  _btn.layer.cornerRadius = frame.size.height/2.0;
  _btn.layer.masksToBounds = YES;
  [_btn setTitleColor:HEXCOLOR(0x666666) forState:UIControlStateNormal];
  _btn.layer.borderColor = HEXCOLOR(0xdddddd).CGColor;
  _btn.userInteractionEnabled = NO;
  [self.contentView addSubview:_btn];
 }
 return self;
}
 
-(void)layoutSubviews
{
 [super layoutSubviews];
 _btn.frame = CGRectMake(0, 0, self.contentView.frame.size.width, self.contentView.frame.size.height);
}
 
-(void)setSelected:(BOOL)selected
{
 [super setSelected:selected];
 _btn.layer.borderColor = selected?HEXCOLOR(0xffb400).CGColor:HEXCOLOR(0xdddddd).CGColor;
 [_btn setTitleColor:selected?HEXCOLOR(0xffb400):HEXCOLOR(0x666666) forState:UIControlStateNormal];
}
 
-(void)setHighlighted:(BOOL)highlighted
{
 [super setHighlighted:highlighted];
 _btn.layer.borderColor = highlighted?HEXCOLOR(0xffb400).CGColor:HEXCOLOR(0xdddddd).CGColor;
 [_btn setTitleColor:highlighted?HEXCOLOR(0xffb400):HEXCOLOR(0x666666) forState:UIControlStateNormal];
}
 
@end
2.UICollection ViewFlowLayout 하위 클래스--YLWaterFlowLayout 의 실현
헤더 파일

#import <UIKit/UIKit.h>
 
@class YLWaterFlowLayout;
@protocol YLWaterFlowLayoutDelegate <NSObject>
/**        cell   */
- (CGFloat)waterFlowLayout:(YLWaterFlowLayout *)layout 
widthAtIndexPath:(NSIndexPath *)indexPath;
 
@end
 
@interface YLWaterFlowLayout : UICollectionViewFlowLayout
@property (nonatomic,assign) id<YLWaterFlowLayoutDelegate> delegate;
@property(nonatomic,assign)CGFloat rowHeight;///<     
 
@end
파일

#import "YLWaterFlowLayout.h"
 
@interface YLWaterFlowLayout()
@property(nonatomic,strong)NSMutableArray *originxArray;
@property(nonatomic,strong)NSMutableArray *originyArray;
@end
 
@implementation YLWaterFlowLayout
#pragma mark -      
- (instancetype)init {
 self = [super init];
 if (self) {
  self.minimumInteritemSpacing = 5;//     cell  
  self.minimumLineSpacing = 5;//   
  self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
  self.scrollDirection = UICollectionViewScrollDirectionVertical;
  _originxArray = [NSMutableArray array];
  _originyArray = [NSMutableArray array];
 }
 return self;
}
 
#pragma mark -        ,       
#pragma mark -         ,    
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
 return YES;
}
 
- (void)prepareLayout {
 [super prepareLayout];
}
 
#pragma mark -      Item layoutAttributes
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
 NSArray *array = [super layoutAttributesForElementsInRect:rect];
 NSMutableArray *mutArray = [NSMutableArray arrayWithCapacity:array.count];
 for(UICollectionViewLayoutAttributes *attrs in array){
  UICollectionViewLayoutAttributes *theAttrs = [self layoutAttributesForItemAtIndexPath:attrs.indexPath];
  [mutArray addObject:theAttrs];
 }
 return mutArray;
}
 
#pragma mark -      Item layoutAttributes
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
 CGFloat x = self.sectionInset.left;
 CGFloat y = self.sectionInset.top;
 //       cell x y
 NSInteger preRow = indexPath.row - 1;
 if(preRow >= 0){
  if(_originyArray.count > preRow){
   x = [_originxArray[preRow]floatValue];
   y = [_originyArray[preRow]floatValue];
  }
  NSIndexPath *preIndexPath = [NSIndexPath indexPathForItem:preRow inSection:indexPath.section];
  CGFloat preWidth = [self.delegate waterFlowLayout:self widthAtIndexPath:preIndexPath];
  x += preWidth + self.minimumInteritemSpacing;
 }
 
 CGFloat currentWidth = [self.delegate waterFlowLayout:self widthAtIndexPath:indexPath];
 //    cell       
 currentWidth = MIN(currentWidth, self.collectionView.frame.size.width - self.sectionInset.left - self.sectionInset.right);
 if(x + currentWidth > self.collectionView.frame.size.width - self.sectionInset.right){
  //    ,  
  x = self.sectionInset.left;
  y += _rowHeight + self.minimumLineSpacing;
 }
 //     
 UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
 attrs.frame = CGRectMake(x, y, currentWidth, _rowHeight);
 _originxArray[indexPath.row] = @(x);
 _originyArray[indexPath.row] = @(y);
 return attrs;
}
 
#pragma mark - CollectionView     
- (CGSize)collectionViewContentSize
{
 CGFloat width = self.collectionView.frame.size.width;
 
 __block CGFloat maxY = 0;
 [_originyArray enumerateObjectsUsingBlock:^(NSNumber *number, NSUInteger idx, BOOL * _Nonnull stop) {
  if ([number floatValue] > maxY) {
   maxY = [number floatValue];
  }
 }];
 
 return CGSizeMake(width, maxY + _rowHeight + self.sectionInset.bottom);
}
 
@end
아이디어 구현:YLWaterFlowLayout 에서 origin xArray 와 originyArray 두 개의 배열 을 사용 하여 사용자 정의 YLTags Collection View Cell 의 위치 x 와 y 를 기록 합 니 다.
-(UICollection View Layout Attributes*)layout Attributes Foritem AtIndexPath:(NSIndexPath*)indexPath 방법 에서 현재 YLTags Collection ViewCell 과 가 까 운'이전 YLTags Collection ViewCell'의 위치 와 사이즈 정 보 를 얻 을 수 있 습 니 다.이전 cell 의 x 에 하나의 cell width 를 더 해서 현재 cell 의 x 를 얻 을 수 있 습 니 다.또한 현재 cell 의 x+width 가 화면 오른쪽 가장 자 리 를 뛰 어 넘 을 지 판단 해 야 합 니 다.초과 하면 줄 을 바 꿔 표시 해 야 한 다 는 뜻 입 니 다.이 럴 때 y 의 값 을 수정 해 야 합 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기