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