iOS实现书架布局样式【一些电子书的首页】
本文实现了类似电子书首页,用来展示图书或小说的布局页面,书架列表【iPhone6模拟器】,屏幕尺寸还没进行适配,只是做个简单的demo【纯代码实现方式】
实现采用的是UICollectionView和UICollectionViewFlowLayout。关于UICollectionView的详细讲解请参考http://blog.csdn.net/meegomeego/article/details/16953489
一、实现layout的DecorationView
// // FWBookShelfDecarationViewCollectionReusableView.h // FWPersonalApp // // Created by hzkmn on 16/2/18. // Copyright © 2016年 ForrstWoo. All rights reserved. // #import <UIKit/UIKit.h> extern NSInteger const kDecorationViewHeight; @interface FWBookShelfDecarationView : UICollectionReusableView @end
// // FWBookShelfDecarationViewCollectionReusableView.m // FWPersonalApp // // Created by hzkmn on 16/2/18. // Copyright © 2016年 ForrstWoo. All rights reserved. // #import "FWBookShelfDecarationView.h" NSInteger const kDecorationViewHeight = 216; @implementation FWBookShelfDecarationView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, screenSize.width, kDecorationViewHeight)]; img.image = [UIImage imageNamed:@"boolshelf.png"]; [self addSubview:img]; } return self; } @end
FWBookShelfDecarationView类非常简单只是定义了Decarationview的背景图片,图上。
二、下载及导入可重新排序的第三方layout,用于我们移动图书后重新布局
详见http://www.cnblogs.com/salam/p/5205919.html
三、实现自己的layout
首先继承LXReorderableCollectionViewFlowLayout,让该类具有重新排序功能。
// // FWBookshelfCollectionViewLayout.h // FWPersonalApp // // Created by hzkmn on 16/2/18. // Copyright © 2016年 ForrstWoo. All rights reserved. // #import "LXReorderableCollectionViewFlowLayout.h" extern NSString * const FWBookshelfCollectionViewLayoutDecorationViewKind; @interface FWBookshelfCollectionViewLayout : LXReorderableCollectionViewFlowLayout @end
// // FWBookshelfCollectionViewLayout.m // FWPersonalApp // // Created by hzkmn on 16/2/18. // Copyright © 2016年 ForrstWoo. All rights reserved. // #import "FWBookshelfCollectionViewLayout.h" #import "FWBookShelfDecarationView.h" NSString * const FWBookshelfCollectionViewLayoutDecorationViewKind = @"FWBookshelfCollectionViewLayoutDecorationViewKind"; @interface FWBookshelfCollectionViewLayout () @property (nonatomic, strong) NSDictionary *bookShelfRectanges; @property NSInteger countOfRow; @end @implementation FWBookshelfCollectionViewLayout - (void)prepareLayout { [super prepareLayout]; [self registerClass:[FWBookShelfDecarationView class] forDecorationViewOfKind:FWBookshelfCollectionViewLayoutDecorationViewKind]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; NSInteger itemCount = [self.collectionView numberOfItemsInSection:0]; self.countOfRow = ceilf(itemCount / 3.0); for (int row = 0; row < self.countOfRow; row++) { dictionary[[NSIndexPath indexPathForItem:row inSection:0]] = [NSValue valueWithCGRect:CGRectMake(0, kDecorationViewHeight * row, screenSize.width, kDecorationViewHeight)]; } self.bookShelfRectanges = [NSDictionary dictionaryWithDictionary:dictionary]; } #pragma mark Runtime Layout Calculations - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { // call super so flow layout can return default attributes for all cells, headers, and footers // NOTE: Flow layout has already taken care of the Cell view layout attributes! :) NSArray *array = [super layoutAttributesForElementsInRect:rect]; // create a mutable copy so we can add layout attributes for any shelfs that // have frames that intersect the rect the CollectionView is interested in NSMutableArray *newArray = [array mutableCopy]; // NSLog(@"in rect:%@",NSStringFromCGRect(rect)); // Add any decoration views (shelves) who's rect intersects with the // CGRect passed to the layout by the CollectionView [self.bookShelfRectanges enumerateKeysAndObjectsUsingBlock:^(id key, id shelfRect, BOOL *stop) { // NSLog(@"[shelfRect CGRectValue]:%@",NSStringFromCGRect([shelfRect CGRectValue])); if (CGRectIntersectsRect([shelfRect CGRectValue], rect)) { UICollectionViewLayoutAttributes *shelfAttributes = [self layoutAttributesForDecorationViewOfKind:FWBookshelfCollectionViewLayoutDecorationViewKind atIndexPath:key]; [newArray addObject:shelfAttributes]; } }]; for (int i = 0; i < [self.collectionView numberOfItemsInSection:0]; i++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; [newArray addObject:[self layoutAttributesForItemAtIndexPath:indexPath]]; } return [newArray copy]; } - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { // NSLog(@"%@", NSStringFromCGSize([self screenSize]));375 667 UICollectionViewLayoutAttributes *attris = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; NSInteger currentRow = indexPath.item / 3; CGRect frame = CGRectMake(20 + (indexPath.item % 3) * (kCellWidth + 17.5), 35+ currentRow * (kCellHeight + 65), kCellWidth, kCellHeight); attris.frame = frame; attris.zIndex = 1; return attris; } - (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath { id shelfRect = self.bookShelfRectanges[indexPath]; // this should never happen, but just in case... if (!shelfRect) return nil; UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath]; attributes.frame = [shelfRect CGRectValue]; // NSLog(@"UICollectionViewLayoutAttributes :.%@", NSStringFromCGRect([shelfRect CGRectValue])); attributes.zIndex = -1; // shelves go behind other views return attributes; } - (CGSize)collectionViewContentSize { CGSize contentSize = CGSizeMake(self.collectionView.bounds.size.width, self.countOfRow * kDecorationViewHeight + 20); return contentSize; } @end
四、应用
// // FWAncientPoetryCollectionViewController.m // FWPersonalApp // // Created by hzkmn on 16/2/17. // Copyright © 2016年 ForrstWoo. All rights reserved. // #import "FWAncientPoetryCollectionViewController.h" #import "FWBookShelfDecarationView.h" #import "FWBookshelfCollectionViewLayout.h" #import "FWBookCategoryViewController.h" @interface FWAncientPoetryCollectionViewController () <LXReorderableCollectionViewDataSource, LXReorderableCollectionViewDelegateFlowLayout> @property (nonatomic, strong) NSMutableArray *books; @end @implementation FWAncientPoetryCollectionViewController static NSString * const cellReuseIdentifier = @"Cell"; - (void)viewDidLoad { [super viewDidLoad]; self.title = @"古籍"; self.collectionView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bookShelfBackground.png"]]; [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellReuseIdentifier]; self.books = [[NSMutableArray alloc] initWithArray:[self bookNameOfAllBooks]]; } - (NSArray *)bookNameOfAllBooks { return [[FWDataManager getDataForPoetry] allKeys]; } #pragma mark <UICollectionViewDataSource> - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 1; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return [self.books count]; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellReuseIdentifier forIndexPath:indexPath]; UIImage *image = [UIImage imageNamed:self.books[indexPath.item]]; cell.backgroundColor = [UIColor colorWithPatternImage:image]; return cell; } - (void)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)fromIndexPath willMoveToIndexPath:(NSIndexPath *)toIndexPath { NSString *theBookName = self.books[fromIndexPath.item]; [self.books removeObjectAtIndex:fromIndexPath.item]; [self.books insertObject:theBookName atIndex:toIndexPath.item]; } #pragma mark - UICollectionViewDelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return CGSizeMake(kCellWidth, kCellHeight); } - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { FWBookCategoryViewController *vc = [[FWBookCategoryViewController alloc] initWithUrlString:[[FWDataManager getDataForPoetry] objectForKey:self.books[indexPath.item]]]; [self.navigationController pushViewController:vc animated:YES]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; [self.books removeAllObjects]; self.books = nil; } @end