iCarousel 是一个用于在 iPhone、iPad 和 Mac OS 上简化各种类型轮播 (分页、滚动视图) 实现的类。iCarousel 实现了多种常见效果,如圆柱形、平面和 "CoverFlow" 样式的轮播,同时提供挂钩用于实现您自己的定制效果。与许多其他 "CoverFlow" 库不同,iCarousel 可以与任何类型的视图一起使用,而不仅仅是图像,因此它非常适合以流畅且引人入胜的方式在您的应用程序中展示分页数据。它还使您能够通过最小化代码更改来轻松地在不同的轮播效果之间进行切换。
注意:'支持'意味着库已测试过此版本。'兼容'表示库应该在此 OS 版本上工作(即它不依赖于任何不可用的 SDK 功能),但不再对兼容性进行测试,可能需要调整或修复错误才能正确运行。
从版本 1.8 开始,iCarousel 需要 ARC。如果您想在非 ARC 项目中使用 iCarousel,只需将编译器标志 -fobjc-arc 添加到 iCarousel.m 类中。要这样做,转到目标设置中的构建阶段选项卡,打开编译源分组,双击列表中的 iCarousel.m,在弹出菜单中输入 -fobjc-arc。
如果您希望将整个项目转换为 ARC,在 iCarousel.m 中注释掉 #error 行,然后在 Xcode 中运行 Edit > Refactor > Convert to Objective-C ARC... 工具,并确保您想要为其使用 ARC 的所有文件都已选中(包括 iCarousel.m)。
iCarousel 从 UIView 衍生而来,并且 - 就像所有 UIKit 组件一样 - 它应该只在主线程中进行访问。您可能希望使用线程来加载或更新轮播内容或项目,但始终确保在更新轮播之前将内容加载到主线程。
要在应用程序中使用 iCarousel 类,只需将 iCarousel 类文件(无需示例文件和资源)拖动到项目中,并添加 QuartzCore 框架。您还可以使用 Cocoapods 以正常的安装方式进行安装。
iCarousel 现已与 Chameleon iOS 到 Mac 转换库(https://github.com/BigZaphod/Chameleon)兼容。要在 Chameleon 中使用 iCarousel,请将 USING_CHAMELEON
添加到您的项目预处理器宏中。查看 Chameleon 演示项目 以了解如何使用 Chameleon 将您的 iOS iCarousel 应用程序移植到 Mac OS - 示例演示了如何使用 Chameleon 在 Mac OS 上运行 No Nib iPhone 示例。请注意,目前点击居中不起作用,滚动必须使用双指滚动手势完成,而不能使用点击和拖动(这都是由于 Chameleon UIGestureRecognizer 实现的特性/限制所致)。
iCarousel 支持以下内置显示类型
您还可以使用 iCarouselTypeCustom
和 carousel:itemTransformForOffset:baseTransform:
协议方法实现您自己的定制轮播样式。
注意:虽然 iCarouselTypeCoverFlow
和 iCarouselTypeCoverFlow2
类型之间的区别非常微妙,但 iCarouselTypeCoverFlow2
的逻辑要复杂得多。如果您滑动轮播,它们基本上是相同的,但如果您用手指缓慢地拖动轮播,应该可以很明显地看到差异。iCarouselTypeCoverFlow2
设计来尽可能地模拟标准的 Apple CoverFlow 效果,并且可能会在未来为这个目标进行细微的变化。
iCarousel 有以下属性(注意:在 Mac OS 上使用属性时,用 NSView 代替 UIView)
@property (nonatomic, weak) IBOutlet id<iCarouselDataSource> dataSource;
支持 iCarouselDataSource 协议的对象,可以提供视图以填充轮播。
@property (nonatomic, weak) IBOutlet id<iCarouselDelegate> delegate;
支持 iCarouselDelegate 协议的对象,可以响应用户轮播事件和布局请求。
@property (nonatomic, assign) iCarouselType type;
用于切换旋转木马的显示类型(见上方详细说明)。
@property (nonatomic, assign) CGFloat perspective;
用于调整各种3D旋转木马视野的透视缩短效果。应为负值,小于0和大于-0.01。超出此范围的值会产生非常奇怪的结果。默认值为-1/500,或-0.005。
@property (nonatomic, assign) CGSize contentOffset;
此属性用于调整旋转木马项视图相对于旋转木马中心的偏移量。默认值为CGSizeZero,意味着旋转木马项目居中。更改此值将移动旋转木马项目而不更改它们的透视,即消失点随着旋转木马项目一起移动,所以如果您将旋转木马项目向下移动,不会显现出您在俯视旋转木马。
@property (nonatomic, assign) CGSize viewpointOffset;
此属性用于调整用户视野相对于旋转木马项目的位置。它与调整contentOffset的效果相反,即如果您向上移动视点,则旋转木马看起来像是向下移动。与contentOffset不同,移动视点也会更改相对于旋转木马项目的透视消失点,所以如果您向上移动视点,看起来就像是在俯视旋转木马。
@property (nonatomic, assign) CGFloat decelerationRate;
旋转木马在被轻扫时的减速速率。较高的值意味着减速较慢。默认值为0.95。值应在0.0(旋转木马在释放时立即停止)到1.0(旋转木马无限期地继续,除非它到达末尾)之间。
@property (nonatomic, assign) BOOL bounces;
设置旋转木马是否应该弹跳经过末尾并返回,或停止不动。请注意,这对此类旨在包裹的旋转木马或carouselShouldWrap代理方法返回YES的情况没有影响。
@property (nonatomic, assign) CGFloat bounceDistance;
非包裹式旋转木马超出末尾时的最大弹跳距离。这是以itemWidth的倍数来衡量的,所以值为1.0表示旋转木马将弹跳一个整个项目的宽度,值为0.5表示半个项目的宽度,等等。默认值为1.0。
@property (nonatomic, assign, getter = isScrollEnabled) BOOL scrollEnabled;
启用和禁用用户的滚动。如果此属性设置为NO,旋转木马仍可以通过编程进行滚动。
@property (nonatomic, readonly, getter = isWrapEnabled) BOOL wrapEnabled;
如果启用包裹,则返回YES,如果没有则返回NO。此属性是只读的。如果您想覆盖默认值,实现carousel:valueForOption:withDefault:
代理方法,并为iCarouselOptionWrap
返回一个值。
@property (nonatomic, assign, getter = isPagingEnabled) BOOL pagingEnabled;
启用和禁用分页。当分页启用时,用户滚动时旋转木马会在每个项视图中停止,就像UIScrollView的pagingEnabled属性一样。
@property (nonatomic, readonly) NSInteger numberOfItems;
旋转木马中的项目数量(只读)。要设置此值,实现numberOfItemsInCarousel:
数据源方法。请注意,并非所有这些项视图都会在某个时间点加载或可见 - 旋转木马在滚动时按需加载项视图。
@property (nonatomic, readonly) NSInteger numberOfPlaceholders;
旋转木马中要显示的占位符视图数量(只读)。要设置此值,实现numberOfPlaceholdersInCarousel:
数据源方法。
@property (nonatomic, readonly) NSInteger numberOfVisibleItems;
在屏幕上同时显示的最大旋转木马项视图数(只读)。此属性对于性能优化很重要,并且基于旋转木马类型和视图框架自动计算。如果您想覆盖默认值,实现carousel:valueForOption:withDefault:
代理方法,并为iCarouselOptionVisibleItems返回一个值。
@property (nonatomic, strong, readonly) NSArray *indexesForVisibleItems;
包含当前在旋转木马中加载和显示的(包括占位符视图)所有项视图索引的数组。该数组包含NSNumber对象,其整数值与视图的索引匹配。项视图的索引从零开始,并与传递给数据源加载视图的索引相匹配,然而任何可见的占位符视图的索引将是负数(小于零)或大于或等于numberOfItems
。该数组中的占位符视图的索引不等同于与数据源一起使用的占位符视图索引。
@property (nonatomic, strong, readonly) NSArray *visibleItemViews;
当前在轮播图中显示的所有项目视图的数组(只读)。这包括所有可见的占位符视图。此数组中视图的索引不匹配项目索引,但视图的顺序与visibleItemIndexes数组属性中视图的顺序相匹配,即您可以通过从visibleItemIndexes数组检索等效对象来获得此数组中给定视图的项目索引(或者,您可以直接使用indexOfItemView:
方法,这要简单得多)。
@property (nonatomic, strong, readonly) UIView *contentView;
包含轮播图项目视图的视图。如果您想将它们与轮播图项目混合,可以向此视图添加子视图。如果您希望某个视图出现在所有轮播图项目之前或之后,应直接将其添加到iCarousel视图中。请注意,在应用程序运行期间,contentView内视图的顺序可能会频繁且未记录地更改。应将userInteractionEnabled属性设置为NO,以防止与iCarousel的触摸事件处理发生冲突的任何视图添加到contentView中。
@property (nonatomic, assign) CGFloat scrollOffset;
这是轮播图的当前滚动偏移量,它是项目宽度的倍数。此值舍入到最接近的整数是currentItemIndex值。您可以使用此值在轮播图移动时定位其他屏幕元素。如果希望以编程方式使轮播图滑动到特定偏移量,则可以设置此值。这可能在您想禁用内置的手势处理并提供自己的实现时很有用。
@property (nonatomic, readonly) CGFloat offsetMultiplier;
这是用户用手指拖动轮播图时使用的偏移量乘数。这不会影响编程滚动或减速速度。对于大多数轮播图类型,默认值为1.0,但对于CoverFlow样式的轮播图,默认值为2.0,以补偿其项目间距更密的事实,因此必须拖动更远的距离才能移动相同的距离。您不能直接设置此属性,但可以通过实现carouselOffsetMultiplier:
委托方法来覆盖默认值。
@property (nonatomic, assign) NSInteger currentItemIndex;
轮播图中当前居中的项目索引。设置此属性与调用scrollToItemAtIndex:animated:
相同,其中animated参数设置为NO。
@property (nonatomic, strong, readonly) UIView *currentItemView;
轮播图中的当前居中项目视图。此视图的索引与currentItemIndex
匹配。
@property (nonatomic, readonly) CGFloat itemWidth;
轮播图中项目的显示宽度(只读)。此值由使用carousel:viewForItemAtIndex:reusingView:
数据源方法传递给轮播图的第一个视图自动生成。您还可以通过使用carouselItemWidth:
委托方法覆盖此值,这将改变为轮播图分配的空间(但不会调整或缩放项目视图)。
@property (nonatomic, assign) BOOL centerItemWhenSelected;
当设置为YES时,除匹配currentItemIndex的轮播图中其他任何项目都将平滑地动画到中心。点击当前选中的项目将没有效果。默认为YES。
@property (nonatomic, assign) CGFloat scrollSpeed;
这是用户用手指快速滑动轮播图时的滚动速度乘数。默认为1.0。
@property (nonatomic, readonly) CGFloat toggle;
此属性用于iCarouselTypeCoverFlow2
轮播图变换。它被暴露出来,以便您可以使用carousel:itemTransformForOffset:baseTransform:
委托方法实现自己的CoverFlow2样式变体。
@property (nonatomic, assign) BOOL stopAtItemBoundary;
默认情况下,当轮播图被滑动时,它会精确地停止在项目边界。如果您将此属性设置为NO,它将自然停止,然后,如果scrollToItemBoundary设置为YES,则向后或向前滑动到最近的边界。
@property (nonatomic, assign) BOOL scrollToItemBoundary;
默认情况下,每当轮播图停止移动时,它将自动滑动到最近的项边界。如果您将此属性设置为NO,轮播图在停止后不会滑动,并将停留在当前位置,即使它没有完全对齐在当前索引上。例外情况是,如果禁用环绕,并将bounces
设置为YES,则无论此设置如何,如果轮播图停止在轮播图末尾之后,它将自动滚动回第一个或最后一个项目索引。
@property (nonatomic, assign, getter = isVertical) BOOL vertical;
此属性控制轮播是否在屏幕上水平或垂直显示。所有内置轮播类型都支持这两种方向。切换到垂直时,将同时改变轮播布局和在屏幕上的滑动检测方向。请注意,自定义轮播转换不受此属性的影响,但滑动手势方向仍然会受到影响。
@property (nonatomic, readonly, getter = isDragging) BOOL dragging;
如果用户已经开始滚动轮播且尚未释放,则返回YES。
@property (nonatomic, readonly, getter = isDecelerating) BOOL decelerating;
如果用户不再拖动轮播,但轮播仍在移动,则返回YES。
@property (nonatomic, readonly, getter = isScrolling) BOOL scrolling;
如果轮播目前正在程序化滚动,则返回YES。
@property (nonatomic, assign) BOOL ignorePerpendicularSwipes;
如果设置为YES,轮播将忽略与轮播方向垂直的滑动手势。因此对于水平轮播,垂直滑动将被忽略。这意味着您可以在轮播项视图中包含一个垂直滚动的scrollView,并且它仍然可以正常工作。默认为YES。
@property (nonatomic, assign) BOOL clipsToBounds;
这实际上不是iCarousel的属性,而是继承自UIView。这里包含它是因为这是一个经常被忽略的功能。将其设置为YES可以防止轮播项视图溢出其边界。您可以在Interface Builder中通过勾选“剪裁子视图”选项来设置此属性。默认为NO。
@property (nonatomic, assign) CGFloat autoscroll;
可以使用此属性设置轮播滚动以恒定速度。1.0的值将以每秒一个项目的速率向前滚动轮播。自动滚动的值可以是正数或负数,默认为0.0(静止)。如果用户与轮播交互,则自动滚动将停止,当用户停止交互时将重新开始。
carousel类有以下方法(注意:对于Mac OS,请将方法参数中的NSView替换为UIView)。
- (void)scrollToItemAtIndex:(NSInteger)index animated:(BOOL)animated;
这将立即或通过平滑动画将轮播居中于指定的项目。对于包裹轮播,轮播将自动确定滚动最短距离(直接或循環)到项目。如果需要控制滚动方向,或要滚动多个回转,请使用scrollByNumberOfItems方法。
- (void)scrollToItemAtIndex:(NSInteger)index duration:(NSTimeInterval)scrollDuration;
此方法允许您控制轮播滚动到指定索引所需的时间。
- (void)scrollByNumberOfItems:(NSInteger)itemCount duration:(NSTimeInterval)duration;
此方法允许您通过固定距离滚动轮播,测量单位是轮播项宽度。可以根据您希望滚动的方向指定 itemCount 的正数或负数。carousel优雅地处理边界问题,因此如果指定的距离大于轮播中的项目数,则滚动将在到达轮播末尾时夹住(如果禁用包裹),或者无缝循环。
- (void)scrollToOffset:(CGFloat)offset duration:(NSTimeInterval)duration;
这与scrollToItemAtIndex:的功能相同,但允许您滚动到分数偏移量。这可能非常有用,如果您希望实现非常精确的动画效果。请注意,如果将scrollToItemBoundary属性设置为YES,则轮播将在您调用此方法后自动滚动到最近的项索引。
- (void)scrollByOffset:(CGFloat)offset duration:(NSTimeInterval)duration;
这与scrollByNumberOfItems:的功能相同,但允许您通过分数数量的项目滚动。这可能非常有用,如果您希望实现非常精确的动画效果。请注意,如果将scrollToItemBoundary属性设置为YES,则轮播将在您调用此方法后自动滚动到最近的项索引。
- (void)reloadData;
这将从dataSource重新加载所有轮播视图并刷新轮播显示。
- (UIView *)itemViewAtIndex:(NSInteger)index;
返回指定索引的可见项目视图。请注意,索引与轮播的位置相关,而不是与 visibleItemViews
数组中的位置相关,这两者可能不同。传入一个负索引或大于或等于 numberOfItems
的索引,以检索占位符视图。此方法仅适用于可见项目视图,如果指定索引的视图尚未加载,或者索引超出了范围,则将返回 nil。
- (NSInteger)indexOfItemView:(UIView *)view;
轮播中给定项目视图的索引。适用于项目视图和占位符视图,但是占位符视图的索引可能与 dataSource 中使用的索引不匹配,并且可能是负数(有关更多详细信息,请参阅上方的 indexesForVisibleItems
属性)。此方法仅适用于可见项目视图,对于当前未加载的视图将返回 NSNotFound。要获取所有已加载视图的列表,请使用 visibleItemViews
属性。
- (NSInteger)indexOfItemViewOrSubview:(UIView *)view
此方法可以获得传入的视图或包含传入参数的视图的项目索引。通过从传入的视图开始,沿着视图层次结构向上遍历,直到找到项视图,并返回它在轮播中的索引。如果没有找到已加载的项视图,它将返回 NSNotFound。此方法对于处理嵌入在项视图中的控件的事件非常有用。这允许您将所有项控件绑定到视图控制器上的单个操作方法,然后确定触发操作的控制相关项。您可以在 控件演示 示例项目中看到这个技术的一个示例。
- (CGFloat)offsetForItemAtIndex:(NSInteger)index;
返回指定项目索引相对于中心位置的 itemWidth
倍数的偏移量。这是计算视图转换和 alpha 值的相同值,并且可以用来根据在轮播中的位置自定义项目视图。此值将在 carouselDidScroll:
协议方法被调用时对每个视图都会发生变化。
- (UIView *)itemViewAtPoint:(CGPoint)point;
返回处于轮播边界内指定点的最前面的项视图。对于实现您自己的点击检测非常有用。
- (void)removeItemAtIndex:(NSInteger)index animated:(BOOL)animated;
此方法将从轮播中删除项。剩余的项将滑过以填充间隙。请注意,在调用此方法时,数据源不会自动更新,因此后续调用 reloadData 将恢复已删除的项。
- (void)insertItemAtIndex:(NSInteger)index animated:(BOOL)animated;
此方法将在轮播中插入项。将从 dataSource 中请求新项,因此确保在调用此方法之前新项已添加到数据源数据中,否则轮播中可能会出现重复项或在其他地方出问题。
- (void)reloadItemAtIndex:(NSInteger)index animated:(BOOL)animated;
此方法将重新加载指定的项目视图。将从 dataSource 中请求新项。如果 animated 参数为 YES,它将从旧项目视图淡入新项目视图,否则将立即交换。
carousel 按照苹果 conventions for 数据驱动视图提供两个协议接口,iCarouselDataSource 和 iCarouselDelegate。iCarouselDataSource 协议有以下必需的方法(注意:对于 Mac OS,将方法参数中的 UIView 替换为 NSView)
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel;
返回轮播中的项数(视图)。
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view;
返回一个视图用于在轮播图指定索引处显示。参数 reusingView
的工作原理类似于 UIPickerView,轮播图中之前显示过的视图会被传回方法进行回收利用。如果此参数不为 nil,则可以设置它的属性并返回它,而不是创建一个新的视图实例,这可以略微提高性能。与 UITableView 不同,没有 reuseIdentifier 来区分不同的轮播视图类型,因此如果您的轮播图包含多个不同的视图类型,那么您可以忽略这个参数,每次调用该方法时都返回一个新的视图。您应该确保每次调用 carousel:viewForItemAtIndex:reusingView:
方法时,要么返回 reusingView,要么返回一个全新的视图实例,而不是保留自己的可回收视图池,因为为不同的轮播图项索引返回多个相同的视图可能会导致轮播图显示问题。
CarouselDataSource 协议有以下可选方法:
- (NSUInteger)numberOfPlaceholdersInCarousel:(iCarousel *)carousel;
返回将显示在轮播图中的占位符视图的数量。占位符视图用于当轮播图中的项目数量不足以填充轮播图宽度时,您希望在空白空间显示某些内容。它们随轮播图移动,就像任何其他轮播项目一样,但它们不计算在 numberOfItems 值内,也不能设置为当前选中的项。当启用包装时,占位符会隐藏。占位符出现在轮播项目两侧。对于 n 个占位符视图,前 n/2 个将出现在项目视图左侧,下一个 n/2 将出现在右侧。您可以拥有奇数个占位符,在这种情况下,轮播图将是不对称的。
- (UIView *)carousel:(iCarousel *)carousel placeholderViewAtIndex:(NSUInteger)index reusingView:(UIView *)view;
返回将显示为占位符视图的视图。其工作原理与 carousel:viewForItemAtIndex:reusingView:
相同。占位符 reusingViews 存储在一个独立的池中,与用于常规轮播图的 reusingViews 分开,所以如果您的占位符视图与项目视图不同,这不是问题。
CarouselDelegate 协议有以下可选方法:
- (void)carouselWillBeginScrollingAnimation:(iCarousel *)carousel;
每次轮播图即将开始动画滚动时都会调用此方法。这可以是程序性地触发,或者当用户完成滚动轮播图后自动触发,因为轮播图重新对齐。
- (void)carouselDidEndScrollingAnimation:(iCarousel *)carousel;
当轮播图结束动画滚动时调用此方法。
- (void)carouselDidScroll:(iCarousel *)carousel;
每次轮播滚动时都会调用此方法。无论轮播图是程序性地滚动还是通过用户交互滚动,都会调用。
- (void)carouselCurrentItemIndexDidChange:(iCarousel *)carousel;
每当轮播滚动足够远,使得 currentItemIndex 属性改变时,都会调用此方法。无论项目索引是通过程序性更新还是通过用户交互更新,都会调用此方法。
- (void)carouselWillBeginDragging:(iCarousel *)carousel;
当用户开始拖动轮播图时调用此方法。如果用户点击轮播图,或者轮播图是程序性滚动的,它将不会触发。
- (void)carouselDidEndDragging:(iCarousel *)carousel willDecelerate:(BOOL)decelerate;
当用户停止拖动轮播图时调用此方法。willDecelerate 参数表示轮播图是否移动得足够快,需要减速才能停止(即当前索引不一定是对其停止的位置)或者它将停在当前位置。请注意,即使 willDecelerate 为 NO,轮播图仍会自动滚动,直到它与当前索引完全对齐。如果您需要知道它何时完全停止移动,请使用 carouselDidEndScrollingAnimation 代理方法。
- (void)carouselWillBeginDecelerating:(iCarousel *)carousel;
当轮播图开始减速时调用此方法。它通常在 carouselDidEndDragging:willDecelerate: 方法之后立即调用,假设 willDecelerate 为 YES。
- (void)carouselDidEndDecelerating:(iCarousel *)carousel;
当滚动条结束时减速并停止时,将调用此方法。此时,您可以假定currentItemIndex的值是最终的停止值。与以前版本不同,在大多数情况下滚动条将现在精确地停在最后一个索引位置。唯一的例外是在启用了弹跳的非包装滚动条中,如果最终停止位置在滚动条末尾之外,则滚动条将自动滚动,直到与最后一个索引完全对齐。为了后向兼容性,在滚动条减速停止后,它将始终调用scrollToItemAtIndex:animated:
。如果您需要确信滚动条何时完全停止移动,请使用carouselDidEndScrollingAnimation
代理方法。
- (CGFloat)carouselItemWidth:(iCarousel *)carousel;
返回每个滚动条项目的宽度 - 即每个项目视图的空间。如果没有实现该方法,则默认为由carousel:viewForItemAtIndex:reusingView:
dataSource方法返回的第一个项目视图的宽度。此方法应仅用于裁剪或填充视图,如果由carousel:viewForItemAtIndex:reusingView:
返回的视图不正确(例如,如果视图大小不同,或在背景图像中包括影响其大小的阴影或外发光) - 如果您只是想要在视图之间添加一些空间,最好使用iCarouselOptionSpacing
值。
- (CATransform3D)carousel:(iCarousel *)carousel itemTransformForOffset:(CGFloat)offset baseTransform:(CATransform3D)transform;
可以使用此方法为每个滚动条视图提供自定义转换。偏移量是指视图与滚动条中部的距离。当前居中的项目视图偏移量为0.0,右侧的项目偏移量为1.0,左侧的项目偏移量为-1.0,依此类推。要实现线性滚动条样式,您只需将偏移值乘以项目宽度,并将其用作转换的x值。只有如果滚动条类型是iCarouselTypeCustom时,才会调用此方法。
- (CGFloat)carousel:(iCarousel *)carousel valueForOption:(iCarouselOption)option withDefault:(CGFloat)value;
此方法用于自定义标准滚动条类型的参数。通过实现此方法,您可以调整选项,例如,在环形滚动条中显示的项目数量,或在糊状滚动条中的倾斜量,以及是否应该循环以及是否应该在末端淡出等。对于您不感兴趣调整的任何选项,只需返回默认值。这些选项的名称列于下面在iCarouselOption values下。查看选项演示以获取使用此方法的更高级示例。
- (void)carousel:(iCarousel *)carousel didSelectItemAtIndex:(NSInteger)index;
如果用户轻触任何滚动条项目视图(不包括占位符视图),包括当前选中视图,将触发此方法。如果用户轻触当前选中视图中的任何控件(即任何子类控件的视图),则不会触发此方法。
- (BOOL)carousel:(iCarousel *)carousel shouldSelectItemAtIndex:(NSInteger)index;
如果用户轻触任何滚动条项目视图(不包括占位符视图),包括当前选中视图,将触发此方法。该方法旨在提供一个机会来忽略对滚动条的轻触。如果您从这个方法返回YES或没有实现它,则轻触将按正常方式进行处理,并调用carousel:didSelectItemAtIndex:
方法。如果您返回NO,则滚动条将忽略轻触,并继续向上传播视图层次结构。这是一种防止滚动条拦截意图由其他视图处理的触摸事件的不错方式。
这些都是标准滚动条的可调整选项。查看选项演示以查看这些参数的效果示例。
iCarouselOptionWrap
一个布尔值,表示当轮播滚动到末尾时是否应该循环。如果您想当轮播到达末尾时继续循环,则返回YES;如果您想让它停止,则返回NO。通常,圆形轮播类型会默认循环,而线性类型则不会。不用担心返回类型是浮点值——任何非0.0的值都将被视为YES。
iCarouselOptionShowBackfaces
对于某些轮播类型,例如iCarouselTypeCylinder,可以查看某些视图的背面(iCarouselTypeInvertedCylinder现在默认隐藏背面)。如果您想隐藏这些向后看不到的视图,可以为此选项返回NO。要覆盖iCarouselTypeInvertedCylinder的默认背面隐藏,可以返回YES。这个选项对于自定义轮播转换,使视图的背面可见也可能有用。
iCarouselOptionOffsetMultiplier
用户用手指拖动轮播时使用的偏移倍数。它不会影响程序性滚动或减速速度。对于大多数轮播类型,默认为1.0,但是对于类似于CoverFlow风格的轮播,默认为2.0,以补偿其项目间距更密集,所以需要拖动更远才能移动相同的距离。
iCarouselOptionVisibleItems
轮播中可以同时显示的项目视图(包括占位符)的最大数量。这个数量一半的视图将在当前选中项目索引的两侧显示。超出这个数量的视图将在滚动到视图中时才会被加载。这允许轮播包含非常多的项目而不影响性能。iCarousel会基于轮播类型选择合适的默认值,但是您可能希望使用此属性来覆盖该值(例如,如果您实现了自定义轮播类型)。
iCarouselOptionCount
用于旋转、圆柱和轮式转换中的项目的数量。通常这个值会基于视口大小和轮播中的项目数量自动计算,但您可以根据需要覆盖此值以更精确地控制轮播外观。这个属性用于计算轮播的半径,所以另一种选择是直接操作半径。
iCarouselOptionArc
旋转、圆柱和轮式转换的弧度(用弧度表示)。通常默认值是2*M_PI(一个完整的圆),但你可以指定更小的值,例如值M_PI将创建半圆或圆柱。这个属性用于计算轮播半径和角度步长,所以另一种选择是直接操作这些值。
iCarouselOptionRadius
旋转、圆柱和轮式转换的像素/点半径。这个值通常计算得非常精确,使得在指定的弧中恰好适合可见项数。您可以通过操作这个值来增加或减少项目间距(以及圆的半径)。
iCarouselOptionAngle
旋转、圆柱和轮式转换中每个项目之间的角度步长(用弧度表示)。在没有改变半径的情况下操作这个值会导致轮播末尾出现间隙或导致项目重叠。
iCarouselOptionTilt
CoverFlow、CoverFlow2和TimeMachine轮播类型中非中心项目的倾斜值。这个值应该在0.0到1.0的范围内。
iCarouselOptionSpacing
项目视图之间的间距。这个值乘以项目宽度(或如果轮播是垂直的,则为高度)以得到每个项目之间的总空间,所以1.0(默认值)表示视图之间没有空间(除非视图已经包含填充,就像许多示例项目中的那样)。
iCarouselOptionFadeMin
iCarouselOptionFadeMax
iCarouselOptionFadeRange
iCarouselOptionFadeMinAlpha
这四个选项根据它们从当前居中 아이템的距离来控制卡片视图的淡出。FadeMin 是一个视图可以实现的负偏移量最小值,在此之前它开始淡出。FadeMax 是一个视图可以实现的正偏移量最大值,在此之前它开始淡出。FadeRange 是淡出发生距离,使用项目宽度的倍数来衡量(默认为1.0),而FadeMinAlpha 是视图将淡出的最小 Alpha 值(默认为0.0 - 完全透明)。
在iOS上的iCarousel中检测点击视图有两大基本方法。第一种方法就是简单地使用carousel:didSelectItemAtIndex:
代理方法,每当一个项目被点击时,该方法就会被触发。如果您只是对当前居中的项目的点击感兴趣,您可以比较currentItemIndex
属性与该方法索引参数。
另一种选择是,如果您想有更多控制,可以将UIButton或UIControl作为项目视图,并自行处理触摸交互。请参考按钮演示示例项目以了解如何实现此操作(不支持Mac OS;详见下文)。
您还可以在项目视图中嵌套UIControls,并且它们将按预期接收触摸(请参阅控件演示示例项目以了解示例)。
如果您想检测其他类型的交互,如滑动、双击或长按,最简单的方法是在将项目视图或其子视图传递到卡片之前将其关联到UIGestureRecognizer。
请注意,除非您将centerItemWhenSelected
属性设置为NO,否则点击和手势会在除了当前选定的项目视图之外的项目视图上被忽略。
在Mac OS上,目前没有简单的方法可以在iCarousel项目视图中嵌套控件。你不能简单地将NSButton作为或放在你的项目视图中,因为应用于项目视图的转换意味着命中检测工作不正常。我正在调查可能的解决方案(如果您知道如何解决这个问题,请与我联系,或者在GitHub上分叉项目)。
iCarousel包括一系列示例项目来帮助您入门。以下是每个示例的简要提升和描述
Basic iOS Example
这是一个非常简单的iOS示例,展示了如何使用iCarouselCoverflow2类型设置卡片。
iOS Demo
这是一个更复杂的iOS演示应用,展示了所有不同的卡片类型以及动态插入/删除项目等附加功能。
Mac Demo
这是iOS演示的Mac OS移植,重复所有相同的功能。
Buttons Demo
此示例演示了如何在iOS上使用UIButtons作为项目视图以及正确处理事件。
Controls Demo
此示例演示了如何在iOS上嵌套控件到项目视图中,并正确处理事件,同时还展示了如何从 nib 文件加载复杂的项目视图而不是在代码中生成。
Multiple Carousels
此示例演示了如何在单个视图控制器中使用多个卡片。
No Nib Demo
此示例演示了如何在iOS上不使用 nib 文件设置iCarousel。
Storyboard Demo
此示例演示了如何使用Storyboards在iOS 5及更高版本上设置iCarousel。
Offsets Demo
此示例演示了如何使用contentOffset
和viewpointOffset
属性以及它们的影响。
Options Demo
此示例演示了如何使用iCarouselOption API自定义每种卡片类型的外观。
Fading Demo
此示例演示了如何使用iCarouselOption API实现漂亮的边缘淡出效果。
Dynamic View Reflections
本示例演示了如何使用ReflectionView类(https://github.com/nicklockwood/ReflectionView)动态地为您的item视图生成反射效果。这适用于包含子视图或控件的item视图。对于只包含图像的item视图,最好使用“动态图像效果”示例中展示的方法。
Dynamic Image Effects
本示例演示了如何使用FXImageView类(《https://github.com/nicklockwood/FXImageView》)动态生成轮播图像的反射和阴影效果。
Dynamic Downloads
本示例演示了如何使用AsyncImageView类(《https://github.com/nicklockwood/AsyncImageView》)动态下载远程图像,并在轮播界面中显示,而不会阻塞主线程或影响性能。
Downloads & Effects
本示例演示了如何使用FXImageView类(《https://github.com/nicklockwood/FXImageView》)即时下载图像,并在实时应用反射和阴影效果。
Swift Example
本示例演示了如何使用Swift而不是Objective-C来使用iCarousel。
Tables Demo
本示例演示了如何在iCarousel的item视图中使用UITableView,并连接数据源,而不需要使用容器控制器。
Q. Does iCarousel support Swift?
A. Yes, check out Swift Example and Swift3 Example projects.
Q. I upgraded to the new version of iCarousel and it broke my project, how do I get the old one back?
A. Every previous release of iCarousel is tagged as a separate download on github - look in the tags tab.
Q. Can I use iCarousel without a nib file?
A. Yes, check out the *No Nib Demo* for how to set up iCarousel without nibs
Q. Can I use iCarousel with a Storyboard?
A. Yes, this is pretty much the same as using it with a nib file. Check out the *Storyboard Demo* to see how it's done.
Q. How do I prevent iCarousel item views from overflowing their bounds?
A. Set the `clipsToBounds` property to YES on your iCarousel view. You can set this property in Interface Builder by ticking the 'Clip Subviews' option.
Q. I'm getting weird issues where views turn up at the wrong points in the carousel. What's going on?
A. You're probably recycling views in your `carousel:viewForItemAtIndex:reusingView:` using the `reusingView` parameter without setting the view contents each time. Study the demo app more closely and make sure you aren't doing all your item view setup in the wrong place.
Q. I'm loading 50 images in my carousel and I keep running out of memory. How can I fix it?
A. The trick is to load the views on a background thread as the carousel is scrolling instead of loading them all in advance. Check out the *Dynamic Downloads* example for how to do this using the AsyncImageView library. The example is using remote image URLs, but the exact same approach will work just as well for locally hosted images in your app - just create local file URLs using `[NSURL fileUrlWithPath:...]`.
Q. Can I use multiple carousels in the same view controller?
A. Yes, check out the *Multiple Carousels* example for how to do this.
Q. I can't figure out how to use iCarousel in my project, is there a simple example?
A. Yes, check out the *Basic iOS Example* project for a bare-bones implementation. If you're still not clear what's going on, read up about how UITableView works, and once you understand that, iCarousel will make more sense.
Q. In the iCarouselTypeCylinder carousel, the back-side of the item views is visible. How can I hide these views?
A. You can either return NO as the value for the `iCarouselOptionShowBackfaces` option, or set the `view.layer.doubleSided` property of your item views to `NO` to hide them when they are facing backwards.
Q. What is the `reusingView` property for in the `carousel:viewForItemAtIndex:reusingView:` dataSource method?
A. You can improve iCarousel performance by recycling item views when they move offscreen instead of creating a new one each time it's needed. Check if this value is nil, and if not you can re-use this view instead of creating a new one. Note however that the view will still have any subviews or properties you added when it was first created, so be careful not to introduce leaks by re-adding those views each time. You may find it's easier and safer to ignore this paramater and create a fresh view each time if you're not sure what you are doing.
Q. If the views in my carousel all have completely different layouts, should I still use the `reusingView` parameter?
A. Probably not, and unless you have hundreds of views in your carousel, it's unlikely to be worth the trouble.
Q. How can I make iCarousel behave like a UIScrollView with paging enabled?
A. As of version 1.8, iCarousel has a pagingEnabled property that emulates the behaviour of a UIScrollView (see the *Paging Example* project). The bounce physics are not quite the same though, and you may want to consider using the SwipeView library instead (https://github.com/nicklockwood/SwipeView) which is very similar to iCarousel, but based on a UIScrollView under the hood.
Q. I want my carousel items to have a real reflection, but the reflection in the examples is just drawn on. How can I render reflections dynamically?
A. iCarousel doesn't have built-in reflection support, but you can use some additional libraries to do this. Check out the *Dynamic View Reflections* and *Dynamic Image Effects* examples.
Q. I want to download a bunch of images on the fly and display them in my carousel. How can I do that?
A. Downloading images asynchronously and displaying them is quite complex. You can use my AsyncImageView library to simplify the process. Check out the *Dynamic Downloads* example.
Q. What if I want to download images on the fly *and* add a reflection? Can I combine the ReflectionView and AsyncImageView classes?
A. Technically yes, but if you are downloading images you'd be better off using the FXImageView class instead of ReflectionView. Check out the *Downloads & Reflections* example.
Q. The edges of my item views look jaggy. Is there any way to smooth/antialias them?
A. If you include (at least) a single pixel of transparent space around the edge of your item view images then iOS will smooth them automatically. This is because iOS automatically antialiases the pixels inside images, but doesn't antialias the edges of views. Even if your item views are a flat color, it's worth adding a background image of the same color to the views in order to get the smoothing effect.
版本1.8.3
版本1.8.2
版本1.8.1
版本1.8
版本1.7.6
版本1.7.5
版本1.7.4
版本1.7.3
版本1.7.2
版本 1.7.1
版本 1.7
版本 1.6.3
版本 1.6.2
版本 1.6.1
版本 1.6
版本 1.5.8
版本 1.5.7
版本 1.5.6
版本1.5.5
版本1.5.4
版本1.5.3
carouselScrollSpeed
代理方法和用新的offsetMultiplier
属性和carouselOffsetMultiplier
代理方法替换,以控制拖动时的偏移量。版本1.5.2
carousel:shouldSelectItemAtIndex:
代理方法,允许旋转马车选择性地忽略点击。stopAtItemBoundary
和scrollToItemBoundary
属性。iCarouselTypeCoverFlow2
实现。版本1.5.1
toggle
属性公开(用于实现CoverFlow2旋转马车样式)。版本1.5
版本1.4
版本1.3.4
版本1.3.3
版本1.3.2
版本1.3.1
版本1.3
版本1.2.4
版本1.2.3
版本1.2.2
版本1.2.1
版本1.2
版本1.1.2
版本1.1.1
版本1.1
版本1.0