您的位置:首页 > 移动开发 > Android开发

ios 仿android gallery控件

2017-07-04 18:56 295 查看
ios 上没有发现与android gallery类似的控件,因为在项目上须要使用到.採用UICollectionView实现





ViewController.m

#import "ViewController.h"
#import "ImageCell.h"
#import "LineLayout.h"

@interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
@property (nonatomic, strong) NSMutableArray *images;
@property (nonatomic, weak) UICollectionView *collectionView;
@end

@implementation ViewController

static NSString *const ID = @"image";

- (NSMutableArray *)images
{
if (!_images) {
self.images = [[NSMutableArray alloc] init];

for (int i = 1; i<=20; i++) {
[self.images addObject:[NSString stringWithFormat:@"%d", i]];
}
}
return _images;
}

- (void)viewDidLoad {
[super viewDidLoad];

CGFloat w = self.view.frame.size.width;
CGRect rect = CGRectMake(0, 100, w, 200);
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:[[LineLayout alloc] init]];
collectionView.dataSource = self;
collectionView.delegate = self;
[collectionView registerNib:[UINib nibWithNibName:@"ImageCell" bundle:nil] forCellWithReuseIdentifier:ID];
[self.view addSubview:collectionView];
self.collectionView = collectionView;
// collectionViewLayout :
// UICollectionViewLayout
// UICollectionViewFlowLayout
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.collectionView.collectionViewLayout isKindOfClass:[LineLayout class]]) {
[self.collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init] animated:YES];
} else {
[self.collectionView setCollectionViewLayout:[[LineLayout alloc] init] animated:YES];
}
}

#pragma mark - <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.images.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
cell.image = self.images[indexPath.item];
return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// 删除模型数据
[self.images removeObjectAtIndex:indexPath.item];

// 删UI(刷新UI)
[collectionView deleteItemsAtIndexPaths:@[indexPath]];
}

@end


LineLayout.m

#import "LineLayout.h"

static const CGFloat ItemWH = 100;

@implementation LineLayout

- (instancetype)init
{
if (self = [super init]) {
}
return self;
}

/**
*  仅仅要显示的边界发生改变就又一次布局:
内部会又一次调用prepareLayout和layoutAttributesForElementsInRect方法获得全部cell的布局属性
*/
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}

/**
*  用来设置collectionView停止滚动那一刻的位置
*
*  @param proposedContentOffset 原本collectionView停止滚动那一刻的位置
*  @param velocity              滚动速度
*/
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
// 1.计算出scrollView最后会停留的范围
CGRect lastRect;
lastRect.origin = proposedContentOffset;
lastRect.size = self.collectionView.frame.size;

// 计算屏幕最中间的x
CGFloat centerX = proposedContentOffset.x + self.collectionView.frame.size.width * 0.5;

// 2.取出这个范围内的全部属性
NSArray *array = [self layoutAttributesForElementsInRect:lastRect];

// 3.遍历全部属性
CGFloat adjustOffsetX = MAXFLOAT;
for (UICollectionViewLayoutAttributes *attrs in array) {
if (ABS(attrs.center.x - centerX) < ABS(adjustOffsetX)) {
adjustOffsetX = attrs.center.x - centerX;
}
}

return CGPointMake(proposedContentOffset.x + adjustOffsetX, proposedContentOffset.y);
}

/**
*  一些初始化工作最好在这里实现
*/
- (void)prepareLayout
{
[super prepareLayout];

// 每个cell的尺寸
self.itemSize = CGSizeMake(ItemWH, ItemWH);
CGFloat inset = (self.collectionView.frame.size.width - HMItemWH) * 0.5;
self.sectionInset = UIEdgeInsetsMake(0, inset, 0, inset);
// 设置水平滚动
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.minimumLineSpacing = ItemWH * 0.7;

// 每个cell(item)都有自己的UICollectionViewLayoutAttributes
// 每个indexPath都有自己的UICollectionViewLayoutAttributes
}

/** 有效距离:当item的中间x距离屏幕的中间x在HMActiveDistance以内,才会開始放大, 其他情况都是缩小 */
static CGFloat const ActiveDistance = 150;
/** 缩放因素: 值越大, item就会越大 */
static CGFloat const ScaleFactor = 0.6;

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
// 0.计算可见的矩形框
CGRect visiableRect;
visiableRect.size = self.collectionView.frame.size;
visiableRect.origin = self.collectionView.contentOffset;

// 1.取得默认的cell的UICollectionViewLayoutAttributes
NSArray *array = [super layoutAttributesForElementsInRect:rect];
// 计算屏幕最中间的x
CGFloat centerX = self.collectionView.contentOffset.x + self.collectionView.frame.size.width * 0.5;

// 2.遍历全部的布局属性
for (UICollectionViewLayoutAttributes *attrs in array) {
// 假设不在屏幕上,直接跳过
if (!CGRectIntersectsRect(visiableRect, attrs.frame)) continue;

// 每个item的中点x
CGFloat itemCenterX = attrs.center.x;

// 差距越小, 缩放比例越大
// 依据跟屏幕最中间的距离计算缩放比例
CGFloat scale = 1 + ScaleFactor * (1 - (ABS(itemCenterX - centerX) / ActiveDistance));
attrs.transform = CGAffineTransformMakeScale(scale, scale);
}

return array;
}

@end


ImageCell.m

#import "ImageCell.h"

@interface ImageCell()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end

@implementation ImageCell

- (void)awakeFromNib {
self.imageView.layer.borderWidth = 3;
self.imageView.layer.borderColor = [UIColor whiteColor].CGColor;
self.imageView.layer.cornerRadius = 3;
self.imageView.clipsToBounds = YES;
}

- (void)setImage:(NSString *)image
{
_image = [image copy];

self.imageView.image = [UIImage imageNamed:image];
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: