ios 上沒有發現與android gallery類似的控件,由於在項目上需要使用到.采用UICollectionView實現


ViewController.m
#import "ViewController.h" #import "ImageCell.h" #import "LineLayout.h" @interface ViewController ()@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 - - (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
#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