1.相信大家都会很熟练使用UITableView了,但是今天给大家 介绍一个iOS6就已经引入的UICollectionView ,功能更加强大,更加灵活,学会使用它,会 帮你解决很多的问题的!它跟UITableView很相似,所以 熟练使用UICollectionView很简单!
2 。先列举一个简单的例子
效果图1.png
我们可以看到这个流式布局,我们可以自定义 布局,继承与UICollectionViewFlowLayout
我现在将 主要代码 贴出来 ,希望对正在使用UICollectionView的同学有所帮助
自定义 布局,继承与 UICollectionViewFlowLayout
CoustomFlowLayOut.m
- (instancetype)init
{
if (self = [super init]) {
}
return self;
}
/**
- 当collectionView的显示范围发生改变的时候,是否需要重新刷新布局
- 一旦重新刷新布局,就会重新调用下面的方法:
1.prepareLayout
2.layoutAttributesForElementsInRect:方法
*/
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}
/**
- 用来做布局的初始化操作(不建议在init方法中进行布局的初始化操作)
*/
-
(void)prepareLayout
{
[super prepareLayout];// 水平滚动
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 设置内边距
CGFloat inset = (self.collectionView.frame.size.width - self.itemSize.width) * 0.5;
self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
}
/**
UICollectionViewLayoutAttributes attrs;
1.一个cell对应一个UICollectionViewLayoutAttributes对象
2.UICollectionViewLayoutAttributes对象决定了cell的frame
/
/
- 这个方法的返回值是一个数组(数组里面存放着rect范围内所有元素的布局属性)
- 这个方法的返回值决定了rect范围内所有元素的排布(frame)
*/
-
(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
// 获得super已经计算好的布局属性
NSArray *array = [super layoutAttributesForElementsInRect:rect] ;// 计算collectionView最中心点的x值
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;// 在原有布局属性的基础上,进行微调
for (UICollectionViewLayoutAttributes *attrs in array) {
// cell的中心点x 和 collectionView最中心点的x值 的间距
CGFloat delta = ABS(attrs.center.x - centerX);// 根据间距值 计算 cell的缩放比例 CGFloat scale = 1 - delta / self.collectionView.frame.size.width; // 设置缩放比例 attrs.transform = CGAffineTransformMakeScale(scale, scale);
}
return array;
}
/**
- 这个方法的返回值,就决定了collectionView停止滚动时的偏移量
*/
-
(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
// 计算出最终显示的矩形框
CGRect rect;
rect.origin.y = 0;
rect.origin.x = proposedContentOffset.x;
rect.size = self.collectionView.frame.size;// 获得super已经计算好的布局属性
NSArray *array = [super layoutAttributesForElementsInRect:rect];// 计算collectionView最中心点的x值
CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;// 存放最小的间距值
CGFloat minDelta = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attrs in array) {
if (ABS(minDelta) > ABS(attrs.center.x - centerX)) {
minDelta = attrs.center.x - centerX;
}
}// 修改原有的偏移量
proposedContentOffset.x += minDelta;
return proposedContentOffset;
}
自定义cell的话,就是只有一张图片,这里不再赘述,控制器里
mainViewController.m
-
(void)viewDidLoad {
[super viewDidLoad];// 创建布局
CoustomFlowLayOut *layout = [[CoustomFlowLayOut alloc] init];
layout.itemSize = CGSizeMake(100, 100);// 创建CollectionView
CGFloat collectionW = self.view.frame.size.width;
CGFloat collectionH = 200;
CGRect frame = CGRectMake(0, 150, collectionW, collectionH);
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout];
collectionView.dataSource = self;
collectionView.delegate = self;
[self.view addSubview:collectionView];// 注册
[collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([CYPhotoCell class]) bundle:nil] forCellWithReuseIdentifier:CYPhotoId];
}
pragma mark - <UICollectionViewDataSource>
-
(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 20;
} -
(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CYPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CYPhotoId forIndexPath:indexPath];cell.imageName = [NSString stringWithFormat:@"%zd", indexPath.item + 1];
return cell;
}
pragma mark - <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"------%zd", indexPath.item);
}
@end
上边就是 主要的代码,就可以很简单的实现 上边图片的功能
大家还可能 见过商城中的 商品中的布局 ,类似是这样的,
效果图.png
其实上边的这种效果也很容易实现,只要自己 自定义布局就行了,只是这个布局比 上边那种布局更复杂一点,但是整体的思路还是相同的,就是 自定义 布局,自定义cell,然后控制器 来利用使用它们,在这里 我将主要的代码贴出来,让大家参考,希望对大家 深入了解认识UICollectionView有好的帮助
同样的我先贴出 自定义layOut的 代码
.h中
import <UIKit/UIKit.h>
@class MKMasonryViewLayout;
@protocol MKMasonryViewLayoutDelegate <NSObject>
@required
- (CGFloat) collectionView:(UICollectionView) collectionView
layout:(MKMasonryViewLayout) layout
heightForItemAtIndexPath:(NSIndexPath*) indexPath;
@end
@interface MKMasonryViewLayout : UICollectionViewLayout
@property (nonatomic, assign) NSUInteger numberOfColumns;
@property (nonatomic, assign) CGFloat interItemSpacing;
@property (weak, nonatomic) IBOutlet id<MKMasonryViewLayoutDelegate> delegate;
@end
.m中
import "MKMasonryViewLayout.h"
@interface MKMasonryViewLayout (/Private Methods/)
@property (nonatomic, strong) NSMutableDictionary *lastYValueForColumn;
@property (strong, nonatomic) NSMutableDictionary *layoutInfo;
@end
@implementation MKMasonryViewLayout
-(void) prepareLayout {
//集合试图 布局 前 会调用这个方法,在这里将 布局物件的边框都计算好 缓存到某个地方
self.numberOfColumns = 3;
self.interItemSpacing = 12.5;
CGFloat currentColumn = 0;
CGFloat fullWidth = self.collectionView.frame.size.width;
CGFloat availableSpaceExcludingPadding = fullWidth - (self.interItemSpacing * (self.numberOfColumns + 1));
CGFloat itemWidth = availableSpaceExcludingPadding / self.numberOfColumns;//每个物件的宽度
self.lastYValueForColumn = [NSMutableDictionary dictionary];
self.layoutInfo = [NSMutableDictionary dictionary];
NSIndexPath *indexPath;
NSInteger numSections = [self.collectionView numberOfSections];
for(NSInteger section = 0; section < numSections; section++) {
//collectionView 是 横着 排列的,而不是 竖着排列的
NSInteger numItems = [self.collectionView numberOfItemsInSection:section];
//每个 section 上含有几个 nuMItems
for(NSInteger item = 0; item < numItems; item++){
indexPath = [NSIndexPath indexPathForItem:item inSection:section];
UICollectionViewLayoutAttributes *itemAttributes =
[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGFloat x = self.interItemSpacing + (self.interItemSpacing + itemWidth) * currentColumn;
CGFloat y = [self.lastYValueForColumn[@(currentColumn)] doubleValue];
CGFloat height = [((id<MKMasonryViewLayoutDelegate>)self.collectionView.delegate)
collectionView:self.collectionView
layout:self
heightForItemAtIndexPath:indexPath];
itemAttributes.frame = CGRectMake(x, y, itemWidth, height);
y+= height;
y += self.interItemSpacing;
self.lastYValueForColumn[@(currentColumn)] = @(y);
currentColumn ++;
if(currentColumn == self.numberOfColumns) currentColumn = 0;
self.layoutInfo[indexPath] = itemAttributes;
}
}
}
-
(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.layoutInfo.count];
[self.layoutInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath,
UICollectionViewLayoutAttributes *attributes,
BOOL *stop) {if (CGRectIntersectsRect(rect, attributes.frame)) {
[allAttributes addObject:attributes];
}
}];
return allAttributes;
}
-(CGSize) collectionViewContentSize {
NSUInteger currentColumn = 0;
CGFloat maxHeight = 0;
do {
CGFloat height = [self.lastYValueForColumn[@(currentColumn)] doubleValue];
if(height > maxHeight)
maxHeight = height;
currentColumn ++;
} while (currentColumn < self.numberOfColumns);
return CGSizeMake(self.collectionView.frame.size.width, maxHeight);
}
@end
上边就是 完整的把想要的布局 给 布置好了,同样自定义cell这里也不 多谢,现在把 控制器的代码贴出来!
import "SCTViewController.h"
@interface SCTViewController ()<UICollectionViewDataSource, UICollectionViewDelegate, MKMasonryViewLayoutDelegate, UICollectionViewDelegateFlowLayout>
@end
@implementation SCTViewController
-
(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
} -
(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} -
(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
} -
(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 40;
} -
(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier
forIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
return cell;
}
// this will be called if our layout is UICollectionViewFlowLayout
-
(CGSize)collectionView:(UICollectionView )collectionView layout:(UICollectionViewLayout)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat randomHeight = 100 + (arc4random() % 140);
return CGSizeMake(100, randomHeight); // 100 to 240 pixels tall
}
// this will be called if our layout is MKMasonryViewLayout
-
(CGFloat) collectionView:(UICollectionView) collectionView
layout:(MKMasonryViewLayout) layout
heightForItemAtIndexPath:(NSIndexPath*) indexPath {// we will use a random height from 100 - 400
CGFloat randomHeight = 100 + (arc4random() % 140);
return randomHeight;
}
@end
上边的代码就可以实现上图中所要实现的功能,希望可以帮到个位!希望个位提出宝贵意见!
网友评论