iOS開源類iCarousel介紹
iCarousel是一個類,它繼承於UIView,用於簡化實現各種類型的旋轉木馬(分頁滾動視圖)iPhone、iPad和Mac OS。iCarousel實現一些常見的影響如圓柱、平面式的旋轉木馬。經過 iCarousel類的封裝,使iCarousel類的使用方式類似於UITableView的使用,每一個界面類似於一個單元格。 iCarousel內先創建一個可變字典,用於存儲需要顯示的單元格視圖。創建一個父視圖用於顯示單元格視圖,從字典中取出需要顯示的單元格視圖添加到創建父視圖上,用於顯示需要創建的單元格視圖,在iCarousel類的內部對這些需要顯示的單元格視圖進行布局。
CarouselType,即Carousel類型
typedef NS_ENUM(NSUInteger, iCarouselType) { iCarouselTypeLinear = 0, //線性類型 iCarouselTypeRotary, //可旋轉類型 iCarouselTypeInvertedRotary, //反向旋轉類型 iCarouselTypeCylinder, //圓柱類型 iCarouselTypeInvertedCylinder, //反向圓柱類型 iCarouselTypeWheel, //車輪類型 iCarouselTypeInvertedWheel, //反向車輪類型 iCarouselTypeCoverFlow, //封面流類型 iCarouselTypeCoverFlow2, //封面流類型2 iCarouselTypeTimeMachine, //時光機類型 iCarouselTypeInvertedTimeMachine, //反向時光機類型 iCarouselTypeCustom //可自定義Carousel類型 };
1.iCarouselTypeLinear線性類型

2. iCarouselTypeRotary可旋轉類型

3. iCarouselTypeInvertedRotary反向旋轉類型

4. iCarouselTypeCylinder圓柱類型

5. iCarouselTypeInvertedCylinder反向圓柱類型

6. iCarouselTypeWheel車輪類型

7. iCarouselTypeInvertedWheel反向車輪類型

8. iCarouselTypeCoverFlow封面流類型

9. iCarouselTypeCoverFlow2封面流類型2

iCarouselTypeCoverFlow和 iCarouselTypeCoverFlow2樣式的不同之處很細微,如果你輕彈carousel,他們基本上是一樣的,但是如果你使用手指慢慢拖動carousel,不同點就會明顯。iCarouselTypeCoverFlow2 是為了模擬盡可能接近標准的蘋果封面流效果而設計的,並且可能在未來會為了這個目標而巧妙地變化。
10. iCarouselTypeTimeMachine時光機類型

11. iCarouselTypeInvertedTimeMachine反向時光機類型

12. iCarouselTypeCustom可自定義Carousel類型,type設置為iCarouselTypeCustom,在代理函數實現自定義動畫
- (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform

常用屬性介紹
@property (nonatomic, assign) iCarouselType type;
type是carousel展示樣式,上面有介紹。
@property (nonatomic, assign) CGFloat scrollSpeed;
當用戶用手指輕擊carousel時,carousel的滾動速度,默認為1.0。
@property (nonatomic, assign, getter = isScrollEnabled) BOOL scrollEnabled;
能否滾動carousel,如果這個值被設為NO,carousel仍然可以以編程方式被滾動。
@property (nonatomic, assign, getter = isPagingEnabled) BOOL pagingEnabled;
整頁平移是否開啟,一般設置為YES。
@property (nonatomic, assign) BOOL bounces;
設置carousel在超出底部和返回時是否應該彈跳,或者是停止並掛掉。注意,在carousel樣式設置為纏繞樣式時或者carouselShouldWrap代理方法返回為yes時,這個屬性不起作用。
@property (nonatomic, assign) CGFloat scrollOffset;
這是以itemWidth的整數倍來計算的carousel當前的滾動偏移量,這個值,被截取為最接近的整數,是currentItemIndex值。當carousel運動中,你可以使用這個值定位其他屏幕的元素。這個值也可以被編程方式設置如果你想滾動carousel到一個特定的偏移。如果你想禁用內置手勢處理並提供自己的實現時,這個可能有用。
@property (nonatomic, readonly) CGFloat offsetMultiplier;
這是當用戶用手指拖動carousel時偏移量的乘數。它並不影響編程的滾動和減速的速度。對大多數carousel樣式這個默認值是1.0,但是對CoverFlow-style樣式的carousels默認值是2.0,來彌補他們的items在空間上更緊湊,所以必須拖拽更遠來移動相同的距離的事實。你不能直接設置這個值,但是可以通過實現carouselOffsetMultiplier:代理方法來重寫默認值。
@property (nonatomic, readonly) NSInteger numberOfItems;
carousel中 items的數量(只讀),要設置他的話,實現 numberOfItemsInCarousel:這個數據源方法。
@property (nonatomic, readonly) NSInteger numberOfPlaceholders;
在carousel中展示的占位視圖的數量(只讀)。要設置他,實現一下numberOfPlaceholdersInCarousel:這個數據源方法。
@property (nonatomic, readonly) CGFloat itemWidth;
carousel中展示的items的寬度(只讀)。這是自動從使用carousel:viewForItemAtIndex:reusingView:數據源方法第一個傳到carousel中的視圖中繼承來的。你也可以使用carouselItemWidth:代理方法重寫這個值,這個方法會改變分配給carousel items的空間(但是不會對這些item views重寫設置大小或規模)。
@property (nonatomic, assign) BOOL centerItemWhenSelected;
當設置為YES時,點擊任何在carousel 中的item而不是那個匹配currentItemIndex 的視圖,將會使平滑動畫移動到居中位置。點擊當前被選中的item將沒有效果。默認值是YES。
@property (nonatomic, assign) BOOL scrollToItemBoundary;
默認情況下,不管carousel何時停止移動,他會自動滾動到最近的item 邊界。如果你設置這個屬性為NO,carousel停止后將不會滾動且不管在哪兒他都會停下來,即使他不是正好對准當前的索引。有一個特例,如果打包效果被禁止且bounces被設置為YES,然后,不管這個設置是什么,carousel會自動滾回第一個或者最后一個索引,如果它停下來時超出了carousel的底部。
iCarousel方法介紹
- (void)scrollToItemAtIndex:(NSInteger)indexanimated:(BOOL)animated;
顧名思義,這個方法是使carousel滾動到一個特定的item。
- (void)scrollToItemAtIndex:(NSInteger)index duration:(NSTimeInterval)duration;
這個方法允許你來控制carousel使用 多長時間來滾動到特定的索引。
- (void)scrollToOffset:(CGFloat)offsetduration:(NSTimeInterval)duration;
這個方法工作起來和 scrollToItemAtIndex:方法一樣,但是允許你移動到一個微小的偏移。如果你想達到一個非常准確的動畫效果時這個可能有用。注意,如果scrollToItemBoundary屬性被設置為YES,當你調用這個方法之后carousel會自動滾動到最近的item索引。
- (void)scrollByNumberOfItems:(NSInteger)itemCount duration:(NSTimeInterval)duration;
這個方法允許你使用一個固定的距離滾動carousel,以carousel的item寬度來衡量。整數或負數可能由itemCount來具體確定,取決於你希望滾動的方向。iCarousel很好的處理了邊界問題,所以如果你指定了一個大於carousel中items數量的值,滾動或者在到達carousel底部時被夾緊(如果打包被禁止),或者無停頓地包裹。
- (UIView *)itemViewAtIndex:(NSInteger)index;
返回指定索引的item視圖。
- (NSInteger)indexOfItemView:(UIView *)view;
返回carousel視圖的索引。
- (void)removeItemAtIndex:(NSInteger)index animated:(BOOL)animated;//移除視圖 - (void)insertItemAtIndex:(NSInteger)index animated:(BOOL)animated;//插入視圖 - (void)reloadItemAtIndex:(NSInteger)index animated:(BOOL)animated;//刷新視圖
iCarouselDataSource
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel;
返回carousel中界面的數量。
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view;
返回一個在carousel中要在指定索引處顯示的視圖,可以是UIImageView等,也可以自定義UIView。
- (NSUInteger)numberOfPlaceholdersInCarousel:(iCarousel *)carousel
返回在carousel中展示的占位視圖數量。占位視圖用來當carousel中界面太少而不能填滿carousel的寬度,並且你希望在空白的地方顯示一些東西時使用。它們隨着carousel移動並且像其他carousel界面一樣運行,但是它們不占numberOfItems數量,且不能被設置為當前選中的界面。
- (UIView *)carousel:(iCarousel *)carousel placeholderViewAtIndex:(NSUInteger)index reusingView:(UIView *)view;
返回在carousel中展示的占位視圖。
iCarouselDelegate
//carousel將開始滾動動畫 - (void)carouselWillBeginScrollingAnimation:(iCarousel *)carousel; //carousel結束滾動動畫 - (void)carouselDidEndScrollingAnimation:(iCarousel *)carousel; //carousel滾動 - (void)carouselDidScroll:(iCarousel *)carousel; //carousel變化 - (void)carouselCurrentItemIndexDidChange:(iCarousel *)carousel; //開始拖動carousel - (void)carouselWillBeginDragging:(iCarousel *)carousel; //停止拖動carousel - (void)carouselDidEndDragging:(iCarousel *)carousel willDecelerate:(BOOL)decelerate; //carousel開始減速 - (void)carouselWillBeginDecelerating:(iCarousel *)carousel; //carousel完成減速 - (void)carouselDidEndDecelerating:(iCarousel *)carousel; //將要點擊carousel視圖觸發該方法 - (BOOL)carousel:(iCarousel *)carousel shouldSelectItemAtIndex:(NSInteger)index; //點擊carousel視圖觸發該方法,類似於tableView:didSelectRowAtIndexPath:方法 - (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index; - (CGFloat)carouselItemWidth:(iCarousel *)carousel; //自定義carousel動畫 - (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform; - (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value;
iCarousel的自定義動畫實現
創建iCarousel類的對象
- (iCarousel *)myCarousel { CGFloat height = kScreen_Width - 2*PAGE_OFFSET; if (!_myCarousel) { _myCarousel = [[iCarousel alloc] initWithFrame:CGRectMake(0, 100, kScreen_Width, height)]; _myCarousel.dataSource = self; _myCarousel.delegate = self; _myCarousel.bounces = NO; _myCarousel.pagingEnabled = YES; _myCarousel.type = iCarouselTypeCustom; } return _myCarousel; }
- (NSMutableArray *)dataSource { if (!_dataSource) { _dataSource = [[NSMutableArray alloc] init]; [_dataSource addObject:[NSString stringWithFormat:@"style_%@.jpg",@"1"]]; [_dataSource addObject:[NSString stringWithFormat:@"style_%@.jpg",@"2"]]; [_dataSource addObject:[NSString stringWithFormat:@"style_%@.jpg",@"3"]]; [_dataSource addObject:[NSString stringWithFormat:@"style_%@.jpg",@"4"]]; [_dataSource addObject:[NSString stringWithFormat:@"style_%@.jpg",@"5"]]; [_dataSource addObject:[NSString stringWithFormat:@"style_%@.jpg",@"6"]]; [_dataSource addObject:[NSString stringWithFormat:@"style_%@.jpg",@"7"]]; [_dataSource addObject:[NSString stringWithFormat:@"style_%@.jpg",@"8"]]; } return _dataSource; }
#pragma mark - iCarouselDataSource - (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel { return self.dataSource.count; } - (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view { if (view == nil) { CGFloat viewWidth = kScreen_Width - 2*PAGE_OFFSET; view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, viewWidth, viewWidth)]; } ((UIImageView *)view).image = [UIImage imageNamed:[self.dataSource objectAtIndex:index]]; return view; } #pragma mark - iCarouselDelegate - (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform { static CGFloat max_sacle = 1.0f; static CGFloat min_scale = 0.6f; if (offset <= 1 && offset >= -1) { float tempScale = offset < 0 ? 1+offset : 1-offset; float slope = (max_sacle - min_scale) / 1; CGFloat scale = min_scale + slope*tempScale; transform = CATransform3DScale(transform, scale, scale, 1); }else{ transform = CATransform3DScale(transform, min_scale, min_scale, 1); } return CATransform3DTranslate(transform, offset * self.myCarousel.itemWidth * 1.4, 0.0, 0.0); } - (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index { [self showHudTipStr:[NSString stringWithFormat:@"點擊了第%ld張圖片",(long)index]]; }